@hellotext/hellotext 2.4.51 → 2.4.52

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.
@@ -25,18 +25,28 @@ let EventsAPI = /*#__PURE__*/function () {
25
25
  key: "create",
26
26
  value: async function create({
27
27
  headers,
28
- body
28
+ body,
29
+ keepalive = false
29
30
  }) {
30
31
  if (_models.Query.inPreviewMode) {
31
32
  return new _response.Response(true, {
32
33
  received: true
33
34
  });
34
35
  }
35
- const response = await fetch(this.endpoint, {
36
+ const fetchOptions = {
36
37
  method: 'POST',
37
38
  headers,
38
39
  body: JSON.stringify(body)
39
- });
40
+ };
41
+
42
+ // Do not send `keepalive: false`. The track caller opts in only for payloads
43
+ // that fit the browser keepalive budget; omitting the key for larger events
44
+ // preserves normal fetch behavior for rich carts/orders instead of asking
45
+ // the browser to use an unload-safe transport it may reject.
46
+ if (keepalive) {
47
+ fetchOptions.keepalive = true;
48
+ }
49
+ const response = await fetch(this.endpoint, fetchOptions);
40
50
  return new _response.Response(response.status === 200, await response.json());
41
51
  }
42
52
  }]);
package/lib/api/events.js CHANGED
@@ -23,18 +23,28 @@ var EventsAPI = /*#__PURE__*/function () {
23
23
  var _create = _asyncToGenerator(function* (_ref) {
24
24
  var {
25
25
  headers,
26
- body
26
+ body,
27
+ keepalive = false
27
28
  } = _ref;
28
29
  if (Query.inPreviewMode) {
29
30
  return new Response(true, {
30
31
  received: true
31
32
  });
32
33
  }
33
- var response = yield fetch(this.endpoint, {
34
+ var fetchOptions = {
34
35
  method: 'POST',
35
36
  headers,
36
37
  body: JSON.stringify(body)
37
- });
38
+ };
39
+
40
+ // Do not send `keepalive: false`. The track caller opts in only for payloads
41
+ // that fit the browser keepalive budget; omitting the key for larger events
42
+ // preserves normal fetch behavior for rich carts/orders instead of asking
43
+ // the browser to use an unload-safe transport it may reject.
44
+ if (keepalive) {
45
+ fetchOptions.keepalive = true;
46
+ }
47
+ var response = yield fetch(this.endpoint, fetchOptions);
38
48
  return new Response(response.status === 200, yield response.json());
39
49
  });
40
50
  function create(_x) {
package/lib/api/index.cjs CHANGED
@@ -10,6 +10,7 @@ Object.defineProperty(exports, "Response", {
10
10
  }
11
11
  });
12
12
  exports.default = void 0;
13
+ exports.keepaliveFor = keepaliveFor;
13
14
  var _businesses = _interopRequireDefault(require("./businesses"));
14
15
  var _events = _interopRequireDefault(require("./events"));
15
16
  var _forms = _interopRequireDefault(require("./forms"));
@@ -23,6 +24,26 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
23
24
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
24
25
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
25
26
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
27
+ // Browsers keep `fetch(..., { keepalive: true })` requests alive during page
28
+ // unload/navigation, which is exactly the failure mode for analytics events
29
+ // fired from checkout redirects, form submissions, tab closes, and pixel
30
+ // lifecycles. The platform also caps keepalive request bodies around 64KB, and
31
+ // browsers can reject or drop oversized requests instead of making delivery
32
+ // more reliable. Keep the limit below that ceiling so the SDK only opts in when
33
+ // the payload is small enough for the keepalive transport contract.
34
+ const KEEPALIVE_BODY_LIMIT = 60000;
35
+ function keepaliveFor(body) {
36
+ const serializedBody = JSON.stringify(body);
37
+
38
+ // Use byte size when the runtime exposes Blob because non-ASCII JSON can be
39
+ // larger on the wire than its JavaScript string length. The string-length
40
+ // fallback keeps older/non-browser runtimes conservative without pulling in
41
+ // another encoder just for this transport hint.
42
+ if (typeof Blob === 'undefined') {
43
+ return serializedBody.length < KEEPALIVE_BODY_LIMIT;
44
+ }
45
+ return new Blob([serializedBody]).size < KEEPALIVE_BODY_LIMIT;
46
+ }
26
47
  let API = /*#__PURE__*/function () {
27
48
  function API() {
28
49
  _classCallCheck(this, API);
package/lib/api/index.js CHANGED
@@ -9,6 +9,27 @@ import FormsAPI from './forms';
9
9
  import IdentificationsAPI from './identifications';
10
10
  import WebchatsAPI from './webchats';
11
11
  import AcksAPI from './acks';
12
+
13
+ // Browsers keep `fetch(..., { keepalive: true })` requests alive during page
14
+ // unload/navigation, which is exactly the failure mode for analytics events
15
+ // fired from checkout redirects, form submissions, tab closes, and pixel
16
+ // lifecycles. The platform also caps keepalive request bodies around 64KB, and
17
+ // browsers can reject or drop oversized requests instead of making delivery
18
+ // more reliable. Keep the limit below that ceiling so the SDK only opts in when
19
+ // the payload is small enough for the keepalive transport contract.
20
+ var KEEPALIVE_BODY_LIMIT = 60000;
21
+ function keepaliveFor(body) {
22
+ var serializedBody = JSON.stringify(body);
23
+
24
+ // Use byte size when the runtime exposes Blob because non-ASCII JSON can be
25
+ // larger on the wire than its JavaScript string length. The string-length
26
+ // fallback keeps older/non-browser runtimes conservative without pulling in
27
+ // another encoder just for this transport hint.
28
+ if (typeof Blob === 'undefined') {
29
+ return serializedBody.length < KEEPALIVE_BODY_LIMIT;
30
+ }
31
+ return new Blob([serializedBody]).size < KEEPALIVE_BODY_LIMIT;
32
+ }
12
33
  var API = /*#__PURE__*/function () {
13
34
  function API() {
14
35
  _classCallCheck(this, API);
@@ -47,4 +68,5 @@ var API = /*#__PURE__*/function () {
47
68
  return API;
48
69
  }();
49
70
  export { API as default };
50
- export { Response } from './response';
71
+ export { Response } from './response';
72
+ export { keepaliveFor };
package/lib/hellotext.cjs CHANGED
@@ -104,7 +104,12 @@ let Hellotext = /*#__PURE__*/function () {
104
104
  delete body.headers;
105
105
  return await _api.default.events.create({
106
106
  headers,
107
- body
107
+ body,
108
+ // Track is the SDK's unload-sensitive analytics path. Keepalive belongs
109
+ // here rather than on identify/forms/webchat calls because event tracking
110
+ // is allowed to be fire-and-navigate, while those other calls have
111
+ // stronger request/response or interaction contracts.
112
+ keepalive: (0, _api.keepaliveFor)(body)
108
113
  });
109
114
  }
110
115
 
package/lib/hellotext.js CHANGED
@@ -9,7 +9,7 @@ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _d
9
9
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
10
10
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
11
11
  import { Configuration, Event } from './core';
12
- import API, { Response } from './api';
12
+ import API, { Response, keepaliveFor } from './api';
13
13
  import { Business, Fingerprint, FormCollection, Page, Query, Session, User, Webchat } from './models';
14
14
  import { NotInitializedError } from './errors';
15
15
  var Hellotext = /*#__PURE__*/function () {
@@ -101,7 +101,12 @@ var Hellotext = /*#__PURE__*/function () {
101
101
  delete body.headers;
102
102
  return yield API.events.create({
103
103
  headers,
104
- body
104
+ body,
105
+ // Track is the SDK's unload-sensitive analytics path. Keepalive belongs
106
+ // here rather than on identify/forms/webchat calls because event tracking
107
+ // is allowed to be fire-and-navigate, while those other calls have
108
+ // stronger request/response or interaction contracts.
109
+ keepalive: keepaliveFor(body)
105
110
  });
106
111
  });
107
112
  function track(_x2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellotext/hellotext",
3
- "version": "2.4.51",
3
+ "version": "2.4.52",
4
4
  "description": "Hellotext JavaScript Client",
5
5
  "source": "src/index.js",
6
6
  "main": "lib/index.cjs",
package/src/api/events.js CHANGED
@@ -8,16 +8,26 @@ export default class EventsAPI {
8
8
  return Configuration.endpoint('track/events')
9
9
  }
10
10
 
11
- static async create({ headers, body }) {
11
+ static async create({ headers, body, keepalive = false }) {
12
12
  if (Query.inPreviewMode) {
13
13
  return new Response(true, { received: true })
14
14
  }
15
15
 
16
- const response = await fetch(this.endpoint, {
16
+ const fetchOptions = {
17
17
  method: 'POST',
18
18
  headers,
19
19
  body: JSON.stringify(body),
20
- })
20
+ }
21
+
22
+ // Do not send `keepalive: false`. The track caller opts in only for payloads
23
+ // that fit the browser keepalive budget; omitting the key for larger events
24
+ // preserves normal fetch behavior for rich carts/orders instead of asking
25
+ // the browser to use an unload-safe transport it may reject.
26
+ if (keepalive) {
27
+ fetchOptions.keepalive = true
28
+ }
29
+
30
+ const response = await fetch(this.endpoint, fetchOptions)
21
31
 
22
32
  return new Response(response.status === 200, await response.json())
23
33
  }
package/src/api/index.js CHANGED
@@ -5,6 +5,29 @@ import IdentificationsAPI from './identifications'
5
5
  import WebchatsAPI from './webchats'
6
6
  import AcksAPI from './acks'
7
7
 
8
+ // Browsers keep `fetch(..., { keepalive: true })` requests alive during page
9
+ // unload/navigation, which is exactly the failure mode for analytics events
10
+ // fired from checkout redirects, form submissions, tab closes, and pixel
11
+ // lifecycles. The platform also caps keepalive request bodies around 64KB, and
12
+ // browsers can reject or drop oversized requests instead of making delivery
13
+ // more reliable. Keep the limit below that ceiling so the SDK only opts in when
14
+ // the payload is small enough for the keepalive transport contract.
15
+ const KEEPALIVE_BODY_LIMIT = 60000
16
+
17
+ function keepaliveFor(body) {
18
+ const serializedBody = JSON.stringify(body)
19
+
20
+ // Use byte size when the runtime exposes Blob because non-ASCII JSON can be
21
+ // larger on the wire than its JavaScript string length. The string-length
22
+ // fallback keeps older/non-browser runtimes conservative without pulling in
23
+ // another encoder just for this transport hint.
24
+ if (typeof Blob === 'undefined') {
25
+ return serializedBody.length < KEEPALIVE_BODY_LIMIT
26
+ }
27
+
28
+ return new Blob([serializedBody]).size < KEEPALIVE_BODY_LIMIT
29
+ }
30
+
8
31
  export default class API {
9
32
  static get businesses() {
10
33
  return BusinessesAPI
@@ -32,3 +55,4 @@ export default class API {
32
55
  }
33
56
 
34
57
  export { Response } from './response'
58
+ export { keepaliveFor }
package/src/hellotext.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Configuration, Event } from './core'
2
2
 
3
- import API, { Response } from './api'
3
+ import API, { Response, keepaliveFor } from './api'
4
4
  import { Business, Fingerprint, FormCollection, Page, Query, Session, User, Webchat } from './models'
5
5
 
6
6
  import { NotInitializedError } from './errors'
@@ -108,6 +108,11 @@ class Hellotext {
108
108
  return await API.events.create({
109
109
  headers,
110
110
  body,
111
+ // Track is the SDK's unload-sensitive analytics path. Keepalive belongs
112
+ // here rather than on identify/forms/webchat calls because event tracking
113
+ // is allowed to be fire-and-navigate, while those other calls have
114
+ // stronger request/response or interaction contracts.
115
+ keepalive: keepaliveFor(body),
111
116
  })
112
117
  }
113
118