@usermaven/nextjs 1.3.3 → 1.4.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.
Files changed (2) hide show
  1. package/lib/index.es.js +156 -8
  2. package/package.json +1 -1
package/lib/index.es.js CHANGED
@@ -798,6 +798,14 @@ function _findClosestLink(element) {
798
798
  }
799
799
  return null;
800
800
  }
801
+ function _cleanObject(obj) {
802
+ for (var propName in obj) {
803
+ if (obj[propName] === '' || obj[propName] === null || obj[propName] === undefined || (typeof obj[propName] === 'object' && Object.keys(obj[propName]).length === 0)) {
804
+ delete obj[propName];
805
+ }
806
+ }
807
+ return obj;
808
+ }
801
809
 
802
810
  /*
803
811
  * Get the className of an element, accounting for edge cases where element.className is an object
@@ -1407,10 +1415,131 @@ var autocapture = {
1407
1415
  _bind_instance_methods(autocapture);
1408
1416
  _safewrap_instance_methods(autocapture);
1409
1417
 
1418
+ var FormTracking = /** @class */ (function () {
1419
+ function FormTracking(instance, trackingType) {
1420
+ if (trackingType === void 0) { trackingType = 'all'; }
1421
+ this.instance = instance;
1422
+ this.trackingType = trackingType;
1423
+ // Wait for the DOM to be ready
1424
+ if (document.readyState === 'loading') {
1425
+ document.addEventListener('DOMContentLoaded', this.track.bind(this));
1426
+ }
1427
+ else {
1428
+ this.track();
1429
+ }
1430
+ }
1431
+ /**
1432
+ * Track form submit
1433
+ * @description this function will be called on every form submit event to track form submit
1434
+ */
1435
+ FormTracking.prototype.track = function () {
1436
+ var _this = this;
1437
+ this.formElements = document.querySelectorAll('form');
1438
+ if (this.trackingType === 'tagged') {
1439
+ this.formElements = document.querySelectorAll('form[data-um-form]');
1440
+ }
1441
+ this.formElements.forEach(function (form) {
1442
+ form.addEventListener('submit', function (event) {
1443
+ var form = event.target;
1444
+ var props = _this._getFormDetails(form);
1445
+ _this.instance.capture('$form', _cleanObject(props));
1446
+ });
1447
+ });
1448
+ };
1449
+ FormTracking.getInstance = function (instance, trackingType) {
1450
+ if (trackingType === void 0) { trackingType = 'all'; }
1451
+ if (!FormTracking.instance) {
1452
+ FormTracking.instance = new FormTracking(instance, trackingType);
1453
+ }
1454
+ return FormTracking.instance;
1455
+ };
1456
+ FormTracking.prototype._getFormDetails = function (form) {
1457
+ var _this = this;
1458
+ var formDetails = {
1459
+ form_id: form.id,
1460
+ form_name: form.name || '',
1461
+ form_action: form.action,
1462
+ form_method: form.method,
1463
+ };
1464
+ var formFields = form.querySelectorAll('input, select, textarea');
1465
+ // ignore form fields with class um-no-capture
1466
+ var filteredFormFields = Array.from(formFields).filter(function (field) { return !field.classList.contains('um-no-capture'); });
1467
+ filteredFormFields.forEach(function (field, index) {
1468
+ var fieldProps = _this._getFieldProps(field, index);
1469
+ Object.assign(formDetails, fieldProps);
1470
+ });
1471
+ return formDetails;
1472
+ };
1473
+ FormTracking.prototype._getFieldProps = function (field, index) {
1474
+ var _a;
1475
+ var fieldDataAttributes = Object.keys(field.dataset).length ? JSON.stringify(field.dataset) : undefined;
1476
+ var safeValue = this.getSafeText(field);
1477
+ return _a = {},
1478
+ _a["field_" + (index + 1) + "_tag"] = field.tagName.toLowerCase(),
1479
+ _a["field_" + (index + 1) + "_type"] = field instanceof HTMLInputElement ? field.type : undefined,
1480
+ _a["field_" + (index + 1) + "_data_attributes"] = fieldDataAttributes,
1481
+ _a["field_" + (index + 1) + "_id"] = field.id,
1482
+ _a["field_" + (index + 1) + "_value"] = safeValue,
1483
+ _a["field_" + (index + 1) + "_class"] = field.className,
1484
+ _a["field_" + (index + 1) + "_name"] = field.name,
1485
+ _a;
1486
+ };
1487
+ FormTracking.prototype.getSafeText = function (element) {
1488
+ var safeText = '';
1489
+ if ('value' in element && element.type !== "password") {
1490
+ safeText = element.value;
1491
+ }
1492
+ else if (element.hasChildNodes()) {
1493
+ var textNodes = Array.from(element.childNodes).filter(function (node) { return node.nodeType === Node.TEXT_NODE; });
1494
+ safeText = textNodes.map(function (node) { return node.textContent; }).join('');
1495
+ }
1496
+ else {
1497
+ safeText = element.textContent || '';
1498
+ }
1499
+ return this._scrubPotentiallySensitiveValues(safeText);
1500
+ };
1501
+ FormTracking.prototype._scrubPotentiallySensitiveValues = function (text) {
1502
+ if (!this._shouldCaptureValue(text)) {
1503
+ return '<redacted>';
1504
+ }
1505
+ return text;
1506
+ };
1507
+ FormTracking.prototype._shouldCaptureValue = function (value) {
1508
+ if (this._isNullish(value)) {
1509
+ return false;
1510
+ }
1511
+ if (this._isString(value)) {
1512
+ value = this._trim(value);
1513
+ // check to see if input value looks like a credit card number
1514
+ // see: https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9781449327453/ch04s20.html
1515
+ var ccRegex = /^(?:(4[0-9]{12}(?:[0-9]{3})?)|(5[1-5][0-9]{14})|(6(?:011|5[0-9]{2})[0-9]{12})|(3[47][0-9]{13})|(3(?:0[0-5]|[68][0-9])[0-9]{11})|((?:2131|1800|35[0-9]{3})[0-9]{11}))$/;
1516
+ if (ccRegex.test((value || '').replace(/[- ]/g, ''))) {
1517
+ return false;
1518
+ }
1519
+ // check to see if input value looks like a social security number
1520
+ var ssnRegex = /(^\d{3}-?\d{2}-?\d{4}$)/;
1521
+ if (ssnRegex.test(value)) {
1522
+ return false;
1523
+ }
1524
+ }
1525
+ return true;
1526
+ };
1527
+ FormTracking.prototype._isNullish = function (value) {
1528
+ return value === null || value === undefined;
1529
+ };
1530
+ FormTracking.prototype._isString = function (value) {
1531
+ return typeof value === 'string' || value instanceof String;
1532
+ };
1533
+ FormTracking.prototype._trim = function (value) {
1534
+ return value.trim().replace(/^\s+|\s+$/g, '');
1535
+ };
1536
+ return FormTracking;
1537
+ }());
1538
+
1410
1539
  var VERSION_INFO = {
1411
1540
  env: 'production',
1412
- date: '2024-02-28T06:06:37.148Z',
1413
- version: '1.3.3'
1541
+ date: '2024-05-21T10:41:05.452Z',
1542
+ version: '1.4.0'
1414
1543
  };
1415
1544
  var USERMAVEN_VERSION = VERSION_INFO.version + "/" + VERSION_INFO.env + "@" + VERSION_INFO.date;
1416
1545
  var MAX_AGE_TEN_YEARS = 31622400 * 10;
@@ -1765,6 +1894,7 @@ var UsermavenClientImpl = /** @class */ (function () {
1765
1894
  this.randomizeUrl = false;
1766
1895
  this.namespace = "usermaven";
1767
1896
  this.crossDomainLinking = true;
1897
+ this.formTracking = false;
1768
1898
  this.domains = [];
1769
1899
  this.apiKey = "";
1770
1900
  this.initialized = false;
@@ -2083,7 +2213,7 @@ var UsermavenClientImpl = /** @class */ (function () {
2083
2213
  };
2084
2214
  UsermavenClientImpl.prototype.init = function (options) {
2085
2215
  var _this = this;
2086
- var _a, _b, _c, _d, _e;
2216
+ var _a, _b, _c, _d, _e, _f;
2087
2217
  if (isWindowAvailable() && !options.force_use_fetch) {
2088
2218
  if (options.fetch) {
2089
2219
  getLogger().warn("Custom fetch implementation is provided to Usermaven. However, it will be ignored since Usermaven runs in browser");
@@ -2143,6 +2273,7 @@ var UsermavenClientImpl = /** @class */ (function () {
2143
2273
  this.cookieDomain = options.cookie_domain || getCookieDomain();
2144
2274
  this.namespace = options.namespace || "usermaven";
2145
2275
  this.crossDomainLinking = (_a = options.cross_domain_linking) !== null && _a !== void 0 ? _a : true;
2276
+ this.formTracking = (_b = options.form_tracking) !== null && _b !== void 0 ? _b : false;
2146
2277
  this.domains = options.domains ? (options.domains).split(',').map(function (domain) { return domain.trim(); }) : [];
2147
2278
  this.trackingHost = getHostWithProtocol(options["tracking_host"] || "t.usermaven.com");
2148
2279
  this.randomizeUrl = options.randomize_url || false;
@@ -2169,8 +2300,8 @@ var UsermavenClientImpl = /** @class */ (function () {
2169
2300
  var restored = this.propsPersistance.restore();
2170
2301
  if (restored) {
2171
2302
  this.permanentProperties = restored;
2172
- this.permanentProperties.globalProps = (_b = restored.globalProps) !== null && _b !== void 0 ? _b : {};
2173
- this.permanentProperties.propsPerEvent = (_c = restored.propsPerEvent) !== null && _c !== void 0 ? _c : {};
2303
+ this.permanentProperties.globalProps = (_c = restored.globalProps) !== null && _c !== void 0 ? _c : {};
2304
+ this.permanentProperties.propsPerEvent = (_d = restored.propsPerEvent) !== null && _d !== void 0 ? _d : {};
2174
2305
  }
2175
2306
  getLogger().debug("Restored persistent properties", this.permanentProperties);
2176
2307
  }
@@ -2187,6 +2318,7 @@ var UsermavenClientImpl = /** @class */ (function () {
2187
2318
  getLogger().debug('Default Configuration', this.config);
2188
2319
  // this.manageSession(this.config);
2189
2320
  this.manageAutoCapture(this.config);
2321
+ this.manageFormTracking(this.config);
2190
2322
  this.manageCrossDomainLinking({
2191
2323
  cross_domain_linking: this.crossDomainLinking,
2192
2324
  domains: this.domains,
@@ -2221,8 +2353,8 @@ var UsermavenClientImpl = /** @class */ (function () {
2221
2353
  enableAutoPageviews(this);
2222
2354
  }
2223
2355
  this.retryTimeout = [
2224
- (_d = options.min_send_timeout) !== null && _d !== void 0 ? _d : this.retryTimeout[0],
2225
- (_e = options.max_send_timeout) !== null && _e !== void 0 ? _e : this.retryTimeout[1],
2356
+ (_e = options.min_send_timeout) !== null && _e !== void 0 ? _e : this.retryTimeout[0],
2357
+ (_f = options.max_send_timeout) !== null && _f !== void 0 ? _f : this.retryTimeout[1],
2226
2358
  ];
2227
2359
  if (!!options.max_send_attempts) {
2228
2360
  this.maxSendAttempts = options.max_send_attempts;
@@ -2363,6 +2495,18 @@ var UsermavenClientImpl = /** @class */ (function () {
2363
2495
  autocapture.init(this, options);
2364
2496
  }
2365
2497
  };
2498
+ /**
2499
+ * Manage form tracking
2500
+ */
2501
+ UsermavenClientImpl.prototype.manageFormTracking = function (options) {
2502
+ if (!isWindowAvailable() || !this.formTracking || this.formTracking === "none") {
2503
+ return;
2504
+ }
2505
+ getLogger().debug('Form tracking enabled...');
2506
+ // all and true are the same
2507
+ var trackingType = this.formTracking === true ? 'all' : this.formTracking;
2508
+ FormTracking.getInstance(this, trackingType).track();
2509
+ };
2366
2510
  /**
2367
2511
  * Capture an event. This is the most important and
2368
2512
  * frequently used usermaven function.
@@ -2403,12 +2547,16 @@ var UsermavenClientImpl = /** @class */ (function () {
2403
2547
  if (event_name === '$scroll') {
2404
2548
  this.track(event_name, data.properties);
2405
2549
  }
2550
+ // send event if the event is $form
2551
+ if (event_name === '$form') {
2552
+ this.track(event_name, data.properties);
2553
+ }
2406
2554
  };
2407
2555
  UsermavenClientImpl.prototype._calculate_event_properties = function (event_name, event_properties) {
2408
2556
  var _a, _b;
2409
2557
  // set defaults
2410
2558
  var properties = event_properties || {};
2411
- if (event_name === '$snapshot' || event_name === '$scroll') {
2559
+ if (event_name === '$snapshot' || event_name === '$scroll' || event_name === '$form') {
2412
2560
  return properties;
2413
2561
  }
2414
2562
  if (_isArray(this.propertyBlacklist)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usermaven/nextjs",
3
- "version": "1.3.3",
3
+ "version": "1.4.0",
4
4
  "description": "Usermaven JavaScript SDK for NextJS",
5
5
  "author": "Usermaven <hello@usermaven.com>",
6
6
  "license": "MIT",