@subiz/widget-v4 4.1.203 → 4.1.205

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 (45) hide show
  1. package/api.md +646 -706
  2. package/compiled_src/chatbox/Widget.js +5 -1
  3. package/compiled_src/chatbox/main.js +11 -1
  4. package/compiled_src/lib.js +12 -13
  5. package/compiled_src/plugin.js +4 -1
  6. package/compiled_src/store/store.js +20 -4
  7. package/compiled_src/util/event.test.js +38 -0
  8. package/dist/{19df158c2ea.27.js → 1a046b44d1d.27.js} +1 -1
  9. package/dist/{19df158c2ea.339.js → 1a046b44d1d.339.js} +1 -1
  10. package/dist/{19df158c2ea.459.js → 1a046b44d1d.459.js} +1 -1
  11. package/dist/1a046b44d1d.app.js +1 -0
  12. package/dist/{19df158c2ea.chat.html → 1a046b44d1d.chat.html} +1 -1
  13. package/dist/1a046b44d1d.chat.js +1 -0
  14. package/dist/{19df158c2ea.form.html → 1a046b44d1d.form.html} +1 -1
  15. package/dist/1a046b44d1d.form.js +1 -0
  16. package/dist/{19df158c2ea.index.html → 1a046b44d1d.index.html} +1 -1
  17. package/dist/{19df158c2ea.library.html → 1a046b44d1d.library.html} +1 -1
  18. package/dist/1a046b44d1d.library.js +1 -0
  19. package/dist/{19df158c2ea.preview.html → 1a046b44d1d.preview.html} +1 -1
  20. package/dist/1a046b44d1d.preview.js +1 -0
  21. package/dist/1a046b44d1d.webview.js +1 -0
  22. package/dist/27.js +1 -1
  23. package/dist/459.js +1 -1
  24. package/dist/HASH +1 -1
  25. package/dist/screenshoot.js +94 -9
  26. package/package.json +4 -4
  27. package/src/chatbox/Widget.js +5 -1
  28. package/src/chatbox/main.js +13 -1
  29. package/src/lib.js +12 -13
  30. package/src/plugin.js +5 -1
  31. package/src/store/store.js +28 -19
  32. package/src/util/event.test.js +31 -0
  33. package/dist/19df158c2ea.app.js +0 -1
  34. package/dist/19df158c2ea.chat.js +0 -1
  35. package/dist/19df158c2ea.form.js +0 -1
  36. package/dist/19df158c2ea.library.js +0 -1
  37. package/dist/19df158c2ea.preview.js +0 -1
  38. package/dist/19df158c2ea.webview.js +0 -1
  39. /package/dist/{19df158c2ea.127.js → 1a046b44d1d.127.js} +0 -0
  40. /package/dist/{19df158c2ea.132.js → 1a046b44d1d.132.js} +0 -0
  41. /package/dist/{19df158c2ea.185.js → 1a046b44d1d.185.js} +0 -0
  42. /package/dist/{19df158c2ea.278.js → 1a046b44d1d.278.js} +0 -0
  43. /package/dist/{19df158c2ea.490.js → 1a046b44d1d.490.js} +0 -0
  44. /package/dist/{19df158c2ea.74.js → 1a046b44d1d.74.js} +0 -0
  45. /package/dist/{19df158c2ea.997.js → 1a046b44d1d.997.js} +0 -0
@@ -1282,6 +1282,7 @@ __webpack_require__.r(__webpack_exports__);
1282
1282
  window.cancelAnimationFrame(this.animationframe);
1283
1283
  }
1284
1284
  });
1285
+ __webpack_require__.dn(__WEBPACK_DEFAULT_EXPORT__);
1285
1286
  function linearTransform(from, to, t, duration) {
1286
1287
  if (eqFloat(from, to)) return from;
1287
1288
  var s = to - from;
@@ -4120,6 +4121,14 @@ var n,l,u,t,i,o,r,f,e,c={},s=[],a=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine
4120
4121
  /******/ };
4121
4122
  /******/ })();
4122
4123
  /******/
4124
+ /******/ /* webpack/runtime/set anonymous default export name */
4125
+ /******/ (() => {
4126
+ /******/ // set .name for anonymous default exports per ES spec
4127
+ /******/ __webpack_require__.dn = (x) => {
4128
+ /******/ (Object.getOwnPropertyDescriptor(x, "name") || {}).writable || Object.defineProperty(x, "name", { value: "default", configurable: true });
4129
+ /******/ };
4130
+ /******/ })();
4131
+ /******/
4123
4132
  /******/ /* webpack/runtime/publicPath */
4124
4133
  /******/ (() => {
4125
4134
  /******/ __webpack_require__.p = "./";
@@ -4599,6 +4608,7 @@ let trackResponseFn = (param, done) => {
4599
4608
  });
4600
4609
  }
4601
4610
  });
4611
+ __webpack_require__.dn(api);
4602
4612
  function fallbackGCSUrl(url) {
4603
4613
  try {
4604
4614
  const u = new URL(url);
@@ -4673,6 +4683,7 @@ const LIMIT = 80;
4673
4683
  });
4674
4684
  }
4675
4685
  });
4686
+ __webpack_require__.dn(lsdb);
4676
4687
  function lsdb_toString(obj) {
4677
4688
  if (obj === undefined) return 'null';
4678
4689
  return JSON.stringify(obj);
@@ -4977,6 +4988,7 @@ let KvMaxSize = 500;
4977
4988
  this.initialized = false;
4978
4989
  }
4979
4990
  });
4991
+ __webpack_require__.dn(kv);
4980
4992
  ;// ./src/store/api_fake.js
4981
4993
  function api_fake_defineProperty(e, r, t) { return (r = api_fake_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4982
4994
  function api_fake_toPropertyKey(t) { var i = api_fake_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
@@ -5067,6 +5079,7 @@ const OK200 = Promise.resolve({
5067
5079
  };
5068
5080
  }
5069
5081
  });
5082
+ __webpack_require__.dn(api_fake);
5070
5083
  function makeFakeConvo(accid, convoid, userid, agentid) {
5071
5084
  let inteid = accid + '.subizv4.subikon';
5072
5085
  return {
@@ -5365,6 +5378,7 @@ function makeFakeMessages(accid, convoid, userid, agentid) {
5365
5378
  }
5366
5379
  reconnect() {}
5367
5380
  });
5381
+ __webpack_require__.dn(realtime_fake);
5368
5382
  ;// ./src/store/store.js
5369
5383
  function store_defineProperty(e, r, t) { return (r = store_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
5370
5384
  function store_toPropertyKey(t) { var i = store_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
@@ -5537,14 +5551,14 @@ class Store {
5537
5551
  store_defineProperty(this, "checkFormToken", (accid, token) => this.api.checkFormToken(accid, token));
5538
5552
  store_defineProperty(this, "submitForm2", (accid, token, data) => this.api.submitForm2(accid, token, data));
5539
5553
  store_defineProperty(this, "sendPresence", util/* default */.A.throttle(async () => {
5554
+ if (!this._track_page_view) return;
5540
5555
  if (this._die) return dieErr;
5541
5556
  await this.readyGate.entry();
5542
5557
  if (!util/* default */.A.get(this.cache.match('user'), 'id')) return;
5543
5558
  if (util/* default */.A.isUserBanned(this.cache.match('user'))) return;
5544
- if (!this._track_page_view) return;
5545
5559
  let hasfocus = this.browserVisibility === 'visible' && document.hasFocus();
5546
5560
  if (!hasfocus) return this.api.sendLostFocus();
5547
- this.api.sendContentView(this.device, location.href, document.title, this._currentViewingProduct.id, this._currentViewingProduct.source_id, this._currentViewingProduct.sku);
5561
+ this.sendPageview();
5548
5562
  }, 1000, {
5549
5563
  leading: false
5550
5564
  }));
@@ -5638,6 +5652,13 @@ class Store {
5638
5652
  this.sendPresence();
5639
5653
  });
5640
5654
  window.addEventListener('beforeunload', () => this.api.sendLostFocus());
5655
+ this._lastPresenceURL = window.location.href;
5656
+ this._urlCheckInterval = util/* default */.A.setInterval(() => {
5657
+ if (this._die) return util/* default */.A.clearInterval(this._urlCheckInterval);
5658
+ if (this._lastPresenceURL === window.location.href) return;
5659
+ this._lastPresenceURL = window.location.href;
5660
+ this.sendPresence();
5661
+ }, 2_000);
5641
5662
  this.doNotStartBot = () => {
5642
5663
  this._donotstartbot = true;
5643
5664
  };
@@ -6159,12 +6180,20 @@ class Store {
6159
6180
  this.cache.put('payment_methods', pms);
6160
6181
  this.pubsub.publish('account');
6161
6182
  }
6183
+ async sendPageview(p) {
6184
+ if (!p) p = {};
6185
+ let device = Object.assign({}, this.device);
6186
+ if (p.referrer) device.source_referrer = p.referrer;
6187
+ device.page_url = p.url || location.href;
6188
+ device.page_title = p.title || document.title;
6189
+ return this.api.sendContentView(device, p.url || location.href, p.title || document.title, this._currentViewingProduct.id, this._currentViewingProduct.source_id, this._currentViewingProduct.sku);
6190
+ }
6162
6191
  async track(e) {
6163
6192
  if (!e) {
6164
- let out = await this.api.sendContentView(this.device, location.href, document.title, this._currentViewingProduct.id, this._currentViewingProduct.source_id, this._currentViewingProduct.sku);
6193
+ let out = await this.sendPageview();
6165
6194
  let traffic_source = util/* default */.A.get(out, 'body.by.device.source', '');
6166
6195
  if (traffic_source) this.kv.put('traffic_source', traffic_source);
6167
- return;
6196
+ return out;
6168
6197
  }
6169
6198
  if (typeof e === 'object') {
6170
6199
  if (!e.data) e.data = {};
@@ -6673,6 +6702,7 @@ class Store {
6673
6702
  this._die = true;
6674
6703
  this.clearBrowserData();
6675
6704
  util/* default */.A.clearInterval(this._seenInterval);
6705
+ util/* default */.A.clearInterval(this._urlCheckInterval);
6676
6706
  if (this.realtime) this.realtime.stop();
6677
6707
  this.readyGate.close();
6678
6708
  window.removeEventListener('blur', this.sendPresence);
@@ -7820,6 +7850,7 @@ class MessageInput extends common/* Com */.Mw {
7820
7850
  }, 500);
7821
7851
  this.resizeInput = util/* default */.A.throttle(function () {
7822
7852
  const input = this.refMessageInput.current;
7853
+ if (!input) return;
7823
7854
  input.style.setProperty('height', '1em', 'important');
7824
7855
  const height = Math.min(200, input.scrollHeight);
7825
7856
  input.style.setProperty('height', `${height}px`, 'important');
@@ -11290,9 +11321,13 @@ class Widget extends common/* Com */.Mw {
11290
11321
  });
11291
11322
  }
11292
11323
  return (0,preact_module.h)("div", {
11293
- class: cls
11324
+ class: cls,
11325
+ onClick: this.onBgClick
11294
11326
  }, $header, $body);
11295
11327
  }
11328
+ onBgClick(event) {
11329
+ event.stopPropagation();
11330
+ }
11296
11331
  validateForm(formData) {
11297
11332
  let newformdata = {};
11298
11333
  util/* default */.A.map(formData, (field, key) => {
@@ -12194,6 +12229,9 @@ function encode(key) {
12194
12229
  // EXTERNAL MODULE: ./src/chatbox/css.js
12195
12230
  var chatbox_css = __webpack_require__(9278);
12196
12231
  ;// ./src/chatbox/main.js
12232
+ function main_defineProperty(e, r, t) { return (r = main_toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
12233
+ function main_toPropertyKey(t) { var i = main_toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
12234
+ function main_toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
12197
12235
 
12198
12236
 
12199
12237
 
@@ -12203,6 +12241,10 @@ var chatbox_css = __webpack_require__(9278);
12203
12241
  class Main extends common/* Com */.Mw {
12204
12242
  constructor(props) {
12205
12243
  super(props);
12244
+ main_defineProperty(this, "state", {
12245
+ cssReady: false,
12246
+ changing: false
12247
+ });
12206
12248
  this.refButton = (0,preact_module/* createRef */._3)();
12207
12249
  this.refWidget = (0,preact_module/* createRef */._3)();
12208
12250
  }
@@ -12230,9 +12272,6 @@ class Main extends common/* Com */.Mw {
12230
12272
  this.$cssStyleDiv.type = 'text/css';
12231
12273
  this.$cssStyleDiv.id = 'subiz-style-for-' + this.props.plugin.id;
12232
12274
  }
12233
- this.setState({
12234
- cssReady: false
12235
- });
12236
12275
  this.checkExpand();
12237
12276
  this.props.store.onResetCSS(this, () => this.refreshCSS());
12238
12277
  this.props.store.onConvoEvent(this, ev => this.onConvoEvent(ev));
@@ -12244,11 +12283,32 @@ class Main extends common/* Com */.Mw {
12244
12283
  });
12245
12284
  });
12246
12285
  this.refreshCSS();
12286
+ let lastview = this.props.store.matchLastview() || {};
12287
+ let cid = util/* default */.A.get(lastview, 'opts.cid');
12288
+ if (cid) {
12289
+ this._last_cid = cid;
12290
+ this.setState({
12291
+ changing: true
12292
+ }, () => {
12293
+ this.props.store.fetchConvo(cid).then(() => {
12294
+ let convo = this.props.store.matchConvo(cid);
12295
+ if (cid != this._last_cid) return;
12296
+ this.setState({
12297
+ changing: false
12298
+ });
12299
+ if (!convo) return this.showWidget({});
12300
+ });
12301
+ });
12302
+ }
12247
12303
  this.setState({
12248
12304
  cssReady: true
12249
12305
  });
12250
12306
  }
12251
12307
  render() {
12308
+ if (this.state.changing) {
12309
+ if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_changing_ready = util/* default */.A.Date.now();
12310
+ return null;
12311
+ }
12252
12312
  if (!this.state.cssReady) {
12253
12313
  if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_css_not_ready = util/* default */.A.Date.now();
12254
12314
  return null;
@@ -12371,6 +12431,14 @@ class Main extends common/* Com */.Mw {
12371
12431
  this.props.store.updateLastview(newView);
12372
12432
  this.forceUpdate();
12373
12433
  }
12434
+ getCurrentView() {
12435
+ let lastview = this.props.store.matchLastview() || {};
12436
+ return {
12437
+ is_show_widget: util/* default */.A.get(lastview, 'screen') === 'widget',
12438
+ view: util/* default */.A.get(lastview, 'view', ''),
12439
+ conversation_id: util/* default */.A.get(lastview, 'opts.cid', '')
12440
+ };
12441
+ }
12374
12442
  applyMessage(text) {
12375
12443
  this.refWidget.current && this.refWidget.current.applyMessage(text);
12376
12444
  }
@@ -12531,7 +12599,10 @@ function Plugin(plugin, store, $container, lib) {
12531
12599
  }
12532
12600
  domGate.open();
12533
12601
  };
12534
- this.call = (method, param) => domGate.entry().then(() => _ref.current[method](param));
12602
+ this.call = (method, param) => domGate.entry().then(() => {
12603
+ if (!_ref.current || typeof _ref.current[method] !== 'function') return;
12604
+ return _ref.current[method](param);
12605
+ });
12535
12606
  var _destroy = false;
12536
12607
  this.destroy = () => {
12537
12608
  _destroy = true;
@@ -12744,6 +12815,11 @@ class lib_Widget {
12744
12815
  lib_defineProperty(this, "setViewingProduct", p => this.store.linkProduct(p));
12745
12816
  lib_defineProperty(this, "getViewingProduct", () => this.store.getLinkedProduct());
12746
12817
  lib_defineProperty(this, "track", v => this.store.track(v));
12818
+ lib_defineProperty(this, "event", async (type, payload, options) => {
12819
+ await this.store.readyGate.entry();
12820
+ return this.store.api.sendEvent(normalizeCdpEvent(type, payload, options));
12821
+ });
12822
+ lib_defineProperty(this, "pageview", v => this.store.sendPageview(v));
12747
12823
  this.impressionTokens = {};
12748
12824
  this.domGate = new util/* default */.A.Gate();
12749
12825
  this.store = new Store(ApiURL, FileURL, RealtimeURL, inmem, fake);
@@ -13087,6 +13163,15 @@ class lib_Widget {
13087
13163
  this.store.doNotStartBot();
13088
13164
  }
13089
13165
  }
13166
+ function normalizeCdpEvent(type, payload, options) {
13167
+ if (type && typeof type === 'object') return type;
13168
+ let data = {
13169
+ type: type
13170
+ };
13171
+ if (payload !== undefined) data.payload = payload;
13172
+ if (options && typeof options === 'object') data = Object.assign({}, options, data);
13173
+ return data;
13174
+ }
13090
13175
  window.__sbz_WIDGET = lib_Widget;
13091
13176
  /* harmony default export */ const lib = (lib_Widget);
13092
13177
  ;// ./screenshoot.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.203",
3
+ "version": "4.1.205",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -21,7 +21,6 @@
21
21
  "preact": "10.19.3"
22
22
  },
23
23
  "devDependencies": {
24
- "tape": "^5.9.0",
25
24
  "@babel/cli": "^7.28.6",
26
25
  "@babel/core": "^7.29.0",
27
26
  "@babel/plugin-proposal-class-properties": "^7.18.6",
@@ -30,8 +29,9 @@
30
29
  "babel-loader": "^10.1.1",
31
30
  "babel-plugin-syntax-jsx": "^6.18.0",
32
31
  "html-webpack-plugin": "^5.6.7",
33
- "puppeteer": "^24.43.1",
34
- "webpack": "^5.106.2",
32
+ "puppeteer": "^25.0.4",
33
+ "tape": "^5.9.0",
34
+ "webpack": "^5.107.1",
35
35
  "webpack-bundle-analyzer": "^5.3.0",
36
36
  "webpack-cli": "^7.0.2",
37
37
  "webpack-dev-server": "^5.2.4"
@@ -207,13 +207,17 @@ export default class Widget extends Com {
207
207
  )
208
208
  }
209
209
  return (
210
- <div class={cls}>
210
+ <div class={cls} onClick={this.onBgClick}>
211
211
  {$header}
212
212
  {$body}
213
213
  </div>
214
214
  )
215
215
  }
216
216
 
217
+ onBgClick(event) {
218
+ event.stopPropagation()
219
+ }
220
+
217
221
  validateForm(formData) {
218
222
  let newformdata = {}
219
223
  sb.map(formData, (field, key) => {
@@ -32,7 +32,10 @@ export default class Main extends Com {
32
32
  let margin_y = sb.get(chatbox, 'desktop_button.margin_y')
33
33
  chatbox.desktop_widget_max_height = margin_y ? `calc(100% - ${margin_y + 10}px)` : 'calc(100% - 40px)'
34
34
  const PREVIEW_MAX_WIDTH = 340
35
- chatbox.preview_max_width = Math.min(PREVIEW_MAX_WIDTH, chatbox.width) + 'px'
35
+ let previewMaxWidthVal = Math.min(PREVIEW_MAX_WIDTH, chatbox.width)
36
+ // avoid NaN when chatbox.width is undefined or null
37
+ if (Number.isNaN(previewMaxWidthVal) || !previewMaxWidthVal) previewMaxWidthVal = PREVIEW_MAX_WIDTH
38
+ chatbox.preview_max_width = previewMaxWidthVal + 'px'
36
39
  var outcss = sb.replaceCssVariable(css, chatbox)
37
40
  sb.setCss(this.props.plugin.id, this.$cssStyleDiv, outcss)
38
41
  }
@@ -198,6 +201,15 @@ export default class Main extends Com {
198
201
  this.forceUpdate()
199
202
  }
200
203
 
204
+ getCurrentView() {
205
+ let lastview = this.props.store.matchLastview() || {}
206
+ return {
207
+ is_show_widget: sb.get(lastview, 'screen') === 'widget',
208
+ view: sb.get(lastview, 'view', ''),
209
+ conversation_id: sb.get(lastview, 'opts.cid', ''),
210
+ }
211
+ }
212
+
201
213
  applyMessage(text) {
202
214
  this.refWidget.current && this.refWidget.current.applyMessage(text)
203
215
  }
package/src/lib.js CHANGED
@@ -317,21 +317,11 @@ class Widget {
317
317
  getViewingProduct = () => this.store.getLinkedProduct()
318
318
 
319
319
  track = (v) => this.store.track(v)
320
- event = async (v) => {
320
+ event = async (type, payload, options) => {
321
321
  await this.store.readyGate.entry()
322
- return this.store.api.sendEvent(v)
323
- }
324
- pageview = (v) => {
325
- v = v || {}
326
- return this.event({
327
- type: 'content_viewed',
328
- payload: {
329
- url: v.url || location.href,
330
- title: v.title || document.title,
331
- referrer: v.referrer || document.referrer,
332
- },
333
- })
322
+ return this.store.api.sendEvent(normalizeCdpEvent(type, payload, options))
334
323
  }
324
+ pageview = (v) => this.store.sendPageview(v)
335
325
 
336
326
  async setLocale(locale) {
337
327
  await this.domGate.entry()
@@ -413,6 +403,15 @@ class Widget {
413
403
  }
414
404
  }
415
405
 
406
+ function normalizeCdpEvent(type, payload, options) {
407
+ if (type && typeof type === 'object') return type
408
+
409
+ let data = {type: type}
410
+ if (payload !== undefined) data.payload = payload
411
+ if (options && typeof options === 'object') data = Object.assign({}, options, data)
412
+ return data
413
+ }
414
+
416
415
  // for debugging purpose
417
416
  window.__sbz_WIDGET = Widget
418
417
  export default Widget
package/src/plugin.js CHANGED
@@ -115,7 +115,11 @@ function Plugin(plugin, store, $container, lib) {
115
115
  domGate.open()
116
116
  }
117
117
 
118
- this.call = (method, param) => domGate.entry().then(() => _ref.current[method](param))
118
+ this.call = (method, param) =>
119
+ domGate.entry().then(() => {
120
+ if (!_ref.current || typeof _ref.current[method] !== 'function') return
121
+ return _ref.current[method](param)
122
+ })
119
123
 
120
124
  var _destroy = false
121
125
  this.destroy = () => {
@@ -76,6 +76,13 @@ export default class Store {
76
76
  this.sendPresence()
77
77
  })
78
78
  window.addEventListener('beforeunload', () => this.api.sendLostFocus())
79
+ this._lastPresenceURL = window.location.href
80
+ this._urlCheckInterval = sb.setInterval(() => {
81
+ if (this._die) return sb.clearInterval(this._urlCheckInterval)
82
+ if (this._lastPresenceURL === window.location.href) return
83
+ this._lastPresenceURL = window.location.href
84
+ this.sendPresence()
85
+ }, 2_000)
79
86
 
80
87
  this.doNotStartBot = () => {
81
88
  this._donotstartbot = true
@@ -508,24 +515,16 @@ export default class Store {
508
515
  submitForm2 = (accid, token, data) => this.api.submitForm2(accid, token, data)
509
516
  sendPresence = sb.throttle(
510
517
  async () => {
518
+ if (!this._track_page_view) return
511
519
  if (this._die) return dieErr
512
520
  await this.readyGate.entry()
513
521
  if (!sb.get(this.cache.match('user'), 'id')) return // store not init
514
522
  if (sb.isUserBanned(this.cache.match('user'))) return
515
523
 
516
- if (!this._track_page_view) return
517
-
518
524
  let hasfocus = this.browserVisibility === 'visible' && document.hasFocus()
519
525
  if (!hasfocus) return this.api.sendLostFocus()
520
526
 
521
- this.api.sendContentView(
522
- this.device,
523
- location.href,
524
- document.title,
525
- this._currentViewingProduct.id,
526
- this._currentViewingProduct.source_id,
527
- this._currentViewingProduct.sku,
528
- )
527
+ this.sendPageview()
529
528
  },
530
529
  1000, // dont send presence update too tight
531
530
  {leading: false}, // dont send right after load. should send after content_view
@@ -915,21 +914,30 @@ export default class Store {
915
914
  this.pubsub.publish('account')
916
915
  }
917
916
 
917
+ async sendPageview(p) {
918
+ if (!p) p = {}
919
+ let device = Object.assign({}, this.device)
920
+ if (p.referrer) device.source_referrer = p.referrer
921
+ device.page_url = p.url || location.href
922
+ device.page_title = p.title || document.title
923
+ return this.api.sendContentView(
924
+ device,
925
+ p.url || location.href,
926
+ p.title || document.title,
927
+ this._currentViewingProduct.id,
928
+ this._currentViewingProduct.source_id,
929
+ this._currentViewingProduct.sku,
930
+ )
931
+ }
932
+
918
933
  // send the content view, the first presence and record domain
919
934
  async track(e) {
920
935
  if (!e) {
921
- let out = await this.api.sendContentView(
922
- this.device,
923
- location.href,
924
- document.title,
925
- this._currentViewingProduct.id,
926
- this._currentViewingProduct.source_id,
927
- this._currentViewingProduct.sku,
928
- )
936
+ let out = await this.sendPageview()
929
937
 
930
938
  let traffic_source = sb.get(out, 'body.by.device.source', '')
931
939
  if (traffic_source) this.kv.put('traffic_source', traffic_source)
932
- return
940
+ return out
933
941
  }
934
942
 
935
943
  if (typeof e === 'object') {
@@ -1501,6 +1509,7 @@ export default class Store {
1501
1509
  this._die = true
1502
1510
  this.clearBrowserData()
1503
1511
  sb.clearInterval(this._seenInterval)
1512
+ sb.clearInterval(this._urlCheckInterval)
1504
1513
  if (this.realtime) this.realtime.stop()
1505
1514
  this.readyGate.close()
1506
1515
  window.removeEventListener('blur', this.sendPresence)
@@ -0,0 +1,31 @@
1
+ var test = require('tape')
2
+ var {normalizeCdpEvent} = require('./event.js')
3
+
4
+ test('normalize cdp event new signature', (t) => {
5
+ t.deepEqual(
6
+ normalizeCdpEvent('content_viewed', {
7
+ url: 'https://example.com/products/pd2345',
8
+ title: 'Bàn phím cơ không dây',
9
+ }, {event_source_id: 'evt_1234'}),
10
+ {
11
+ type: 'content_viewed',
12
+ payload: {
13
+ url: 'https://example.com/products/pd2345',
14
+ title: 'Bàn phím cơ không dây',
15
+ },
16
+ event_source_id: 'evt_1234',
17
+ },
18
+ )
19
+ t.end()
20
+ })
21
+
22
+ test('normalize cdp event without payload', (t) => {
23
+ t.deepEqual(normalizeCdpEvent('login'), {type: 'login'})
24
+ t.end()
25
+ })
26
+
27
+ test('normalize cdp event keeps old object signature', (t) => {
28
+ let event = {type: 'product_viewed', payload: {id: 'pd2345'}}
29
+ t.equal(normalizeCdpEvent(event), event)
30
+ t.end()
31
+ })