humanbehavior-js 0.1.1 → 0.1.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/dist/cjs/index.js CHANGED
@@ -4368,6 +4368,57 @@ class HumanBehaviorAPI {
4368
4368
  data.append('apiKey', encodeURIComponent(this.apiKey));
4369
4369
  navigator.sendBeacon(`${this.baseUrl}/api/ingestion/events`, data);
4370
4370
  }
4371
+ sendCustomEvent(sessionId, eventName, eventProperties) {
4372
+ return __awaiter$1(this, void 0, void 0, function* () {
4373
+ try {
4374
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/customEvent`, {
4375
+ method: 'POST',
4376
+ headers: {
4377
+ 'Content-Type': 'application/json',
4378
+ 'Authorization': `Bearer ${this.apiKey}`
4379
+ },
4380
+ body: JSON.stringify({
4381
+ sessionId: sessionId,
4382
+ eventName: eventName,
4383
+ eventProperties: eventProperties || {}
4384
+ })
4385
+ });
4386
+ if (!response.ok) {
4387
+ throw new Error(`Failed to send custom event: ${response.statusText}`);
4388
+ }
4389
+ return yield response.json();
4390
+ }
4391
+ catch (error) {
4392
+ logError('Error sending custom event:', error);
4393
+ throw error;
4394
+ }
4395
+ });
4396
+ }
4397
+ sendCustomEventBatch(sessionId, events) {
4398
+ return __awaiter$1(this, void 0, void 0, function* () {
4399
+ try {
4400
+ const response = yield fetch(`${this.baseUrl}/api/ingestion/customEvent/batch`, {
4401
+ method: 'POST',
4402
+ headers: {
4403
+ 'Content-Type': 'application/json',
4404
+ 'Authorization': `Bearer ${this.apiKey}`
4405
+ },
4406
+ body: JSON.stringify({
4407
+ sessionId: sessionId,
4408
+ events: events
4409
+ })
4410
+ });
4411
+ if (!response.ok) {
4412
+ throw new Error(`Failed to send custom event batch: ${response.statusText}`);
4413
+ }
4414
+ return yield response.json();
4415
+ }
4416
+ catch (error) {
4417
+ logError('Error sending custom event batch:', error);
4418
+ throw error;
4419
+ }
4420
+ });
4421
+ }
4371
4422
  }
4372
4423
 
4373
4424
  // Redaction functionality for sensitive input fields
@@ -4806,6 +4857,10 @@ class HumanBehaviorTracker {
4806
4857
  if (options === null || options === void 0 ? void 0 : options.redactFields) {
4807
4858
  tracker.setRedactedFields(options.redactFields);
4808
4859
  }
4860
+ // Setup automatic tracking if enabled
4861
+ if ((options === null || options === void 0 ? void 0 : options.enableAutomaticTracking) !== false) {
4862
+ tracker.setupAutomaticTracking(options === null || options === void 0 ? void 0 : options.automaticTrackingOptions);
4863
+ }
4809
4864
  // Test connection (non-blocking)
4810
4865
  if (isBrowser) {
4811
4866
  const testUrl = tracker.api['baseUrl'] + '/api/health';
@@ -5054,28 +5109,159 @@ class HumanBehaviorTracker {
5054
5109
  if (!this.initialized)
5055
5110
  return;
5056
5111
  try {
5057
- const customEventData = {
5058
- eventName: eventName,
5059
- properties: properties || {},
5060
- timestamp: new Date().toISOString(),
5061
- url: window.location.href,
5062
- pathname: window.location.pathname
5063
- };
5064
- // Add custom event to the main event stream
5065
- yield this.addEvent({
5066
- type: 5, // Custom event type
5067
- data: {
5068
- payload: Object.assign({ eventType: 'custom' }, customEventData)
5069
- },
5070
- timestamp: Date.now()
5071
- });
5112
+ // Send custom event directly to the API
5113
+ yield this.api.sendCustomEvent(this.sessionId, eventName, properties);
5072
5114
  logDebug(`Custom event tracked: ${eventName}`, properties);
5073
5115
  }
5074
5116
  catch (error) {
5075
5117
  logError('Failed to track custom event:', error);
5118
+ // Fallback: add to event stream if direct API call fails
5119
+ try {
5120
+ const customEventData = {
5121
+ eventName: eventName,
5122
+ properties: properties || {},
5123
+ timestamp: new Date().toISOString(),
5124
+ url: window.location.href,
5125
+ pathname: window.location.pathname
5126
+ };
5127
+ yield this.addEvent({
5128
+ type: 5, // Custom event type
5129
+ data: {
5130
+ payload: Object.assign({ eventType: 'custom' }, customEventData)
5131
+ },
5132
+ timestamp: Date.now()
5133
+ });
5134
+ logDebug(`Custom event added to event stream as fallback: ${eventName}`);
5135
+ }
5136
+ catch (fallbackError) {
5137
+ logError('Failed to add custom event to event stream as fallback:', fallbackError);
5138
+ }
5076
5139
  }
5077
5140
  });
5078
5141
  }
5142
+ /**
5143
+ * Setup automatic tracking for buttons, links, and forms
5144
+ */
5145
+ setupAutomaticTracking(options) {
5146
+ if (!isBrowser)
5147
+ return;
5148
+ const config = {
5149
+ trackButtons: (options === null || options === void 0 ? void 0 : options.trackButtons) !== false,
5150
+ trackLinks: (options === null || options === void 0 ? void 0 : options.trackLinks) !== false,
5151
+ trackForms: (options === null || options === void 0 ? void 0 : options.trackForms) !== false,
5152
+ includeText: (options === null || options === void 0 ? void 0 : options.includeText) !== false,
5153
+ includeClasses: (options === null || options === void 0 ? void 0 : options.includeClasses) || false
5154
+ };
5155
+ logDebug('Setting up automatic tracking with config:', config);
5156
+ // Setup button tracking
5157
+ if (config.trackButtons) {
5158
+ this.setupAutomaticButtonTracking(config);
5159
+ }
5160
+ // Setup link tracking
5161
+ if (config.trackLinks) {
5162
+ this.setupAutomaticLinkTracking(config);
5163
+ }
5164
+ // Setup form tracking
5165
+ if (config.trackForms) {
5166
+ this.setupAutomaticFormTracking(config);
5167
+ }
5168
+ }
5169
+ /**
5170
+ * Setup automatic button tracking
5171
+ */
5172
+ setupAutomaticButtonTracking(config) {
5173
+ document.addEventListener('click', (event) => __awaiter$1(this, void 0, void 0, function* () {
5174
+ var _a;
5175
+ const target = event.target;
5176
+ // Track button clicks
5177
+ if (target.tagName === 'BUTTON' || target.closest('button')) {
5178
+ const button = target.tagName === 'BUTTON'
5179
+ ? target
5180
+ : target.closest('button');
5181
+ const properties = {
5182
+ buttonId: button.id || null,
5183
+ buttonType: button.type || 'button',
5184
+ page: window.location.pathname,
5185
+ timestamp: Date.now()
5186
+ };
5187
+ if (config.includeText) {
5188
+ properties.buttonText = ((_a = button.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || null;
5189
+ }
5190
+ if (config.includeClasses) {
5191
+ properties.buttonClass = button.className || null;
5192
+ }
5193
+ // Remove null values
5194
+ Object.keys(properties).forEach(key => {
5195
+ if (properties[key] === null) {
5196
+ delete properties[key];
5197
+ }
5198
+ });
5199
+ yield this.customEvent('button_clicked', properties);
5200
+ }
5201
+ }));
5202
+ }
5203
+ /**
5204
+ * Setup automatic link tracking
5205
+ */
5206
+ setupAutomaticLinkTracking(config) {
5207
+ document.addEventListener('click', (event) => __awaiter$1(this, void 0, void 0, function* () {
5208
+ var _a;
5209
+ const target = event.target;
5210
+ // Track link clicks
5211
+ if (target.tagName === 'A' || target.closest('a')) {
5212
+ const link = target.tagName === 'A'
5213
+ ? target
5214
+ : target.closest('a');
5215
+ const properties = {
5216
+ linkUrl: link.href || null,
5217
+ linkId: link.id || null,
5218
+ linkTarget: link.target || null,
5219
+ page: window.location.pathname,
5220
+ timestamp: Date.now()
5221
+ };
5222
+ if (config.includeText) {
5223
+ properties.linkText = ((_a = link.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || null;
5224
+ }
5225
+ if (config.includeClasses) {
5226
+ properties.linkClass = link.className || null;
5227
+ }
5228
+ // Remove null values
5229
+ Object.keys(properties).forEach(key => {
5230
+ if (properties[key] === null) {
5231
+ delete properties[key];
5232
+ }
5233
+ });
5234
+ yield this.customEvent('link_clicked', properties);
5235
+ }
5236
+ }));
5237
+ }
5238
+ /**
5239
+ * Setup automatic form tracking
5240
+ */
5241
+ setupAutomaticFormTracking(config) {
5242
+ document.addEventListener('submit', (event) => __awaiter$1(this, void 0, void 0, function* () {
5243
+ const form = event.target;
5244
+ const formData = new FormData(form);
5245
+ const properties = {
5246
+ formId: form.id || null,
5247
+ formAction: form.action || null,
5248
+ formMethod: form.method || 'get',
5249
+ fields: Array.from(formData.keys()),
5250
+ page: window.location.pathname,
5251
+ timestamp: Date.now()
5252
+ };
5253
+ if (config.includeClasses) {
5254
+ properties.formClass = form.className || null;
5255
+ }
5256
+ // Remove null values
5257
+ Object.keys(properties).forEach(key => {
5258
+ if (properties[key] === null) {
5259
+ delete properties[key];
5260
+ }
5261
+ });
5262
+ yield this.customEvent('form_submitted', properties);
5263
+ }));
5264
+ }
5079
5265
  /**
5080
5266
  * Cleanup navigation tracking
5081
5267
  */
@@ -5271,6 +5457,7 @@ class HumanBehaviorTracker {
5271
5457
  inlineStylesheet: true,
5272
5458
  recordCanvas: true,
5273
5459
  collectFonts: true,
5460
+ inlineImages: true,
5274
5461
  blockClass: 'rr-block',
5275
5462
  ignoreClass: 'rr-ignore',
5276
5463
  maskTextClass: 'rr-ignore'