@saasquatch/squatch-js 2.4.3 → 2.5.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.
- package/CHANGELOG.md +326 -291
- package/LICENSE +20 -20
- package/demo/sandbox.ts +7 -5
- package/demo/toolbar.tsx +1 -1
- package/dist/api/AnalyticsApi.d.ts +1 -1
- package/dist/api/WidgetApi.d.ts +2 -15
- package/dist/api/graphql.d.ts +1 -0
- package/dist/squatch.d.ts +10 -2
- package/dist/squatch.esm.js +264 -153
- package/dist/squatch.esm.js.map +1 -1
- package/dist/squatch.js +266 -153
- package/dist/squatch.js.map +1 -1
- package/dist/squatch.min.js +3 -3
- package/dist/squatch.min.js.map +1 -1
- package/dist/squatch.modern.js +1 -1
- package/dist/squatch.modern.js.map +1 -1
- package/dist/stats.html +1 -1
- package/dist/types.d.ts +10 -4
- package/dist/utils/cookieUtils.d.ts +1 -0
- package/dist/utils/io.d.ts +1 -0
- package/dist/utils/utmUtils.d.ts +14 -0
- package/dist/utils/validate.d.ts +2 -0
- package/dist/widgets/Widgets.d.ts +3 -17
- package/package.json +104 -104
package/dist/squatch.esm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as debug from 'debug';
|
|
2
2
|
import debug__default from 'debug';
|
|
3
3
|
import * as EventBus from 'eventbusjs';
|
|
4
|
-
import * as superagent from 'superagent';
|
|
5
4
|
import Cookies from 'js-cookie';
|
|
5
|
+
import * as superagent from 'superagent';
|
|
6
6
|
|
|
7
7
|
function _extends() {
|
|
8
8
|
_extends = Object.assign || function (target) {
|
|
@@ -22,6 +22,45 @@ function _extends() {
|
|
|
22
22
|
return _extends.apply(this, arguments);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
26
|
+
if (source == null) return {};
|
|
27
|
+
var target = {};
|
|
28
|
+
var sourceKeys = Object.keys(source);
|
|
29
|
+
var key, i;
|
|
30
|
+
|
|
31
|
+
for (i = 0; i < sourceKeys.length; i++) {
|
|
32
|
+
key = sourceKeys[i];
|
|
33
|
+
if (excluded.indexOf(key) >= 0) continue;
|
|
34
|
+
target[key] = source[key];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return target;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function doQuery(url, query, variables, token) {
|
|
41
|
+
const headers = _extends({
|
|
42
|
+
Accept: "application/json"
|
|
43
|
+
}, token ? {
|
|
44
|
+
Authorization: `Bearer ${token}`
|
|
45
|
+
} : {}, {
|
|
46
|
+
"X-SaaSquatch-Referrer": window ? window.location.href : ""
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const request = superagent.post(url).send({
|
|
50
|
+
query,
|
|
51
|
+
variables
|
|
52
|
+
}).set(headers);
|
|
53
|
+
return thenableSuperagent(request).then(response => response, error => {
|
|
54
|
+
let json;
|
|
55
|
+
|
|
56
|
+
try {
|
|
57
|
+
json = JSON.parse(error.response.text);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throw json;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
25
64
|
function doGet(url, jwt = "") {
|
|
26
65
|
const headers = {
|
|
27
66
|
Accept: "application/json",
|
|
@@ -158,12 +197,37 @@ function validateConfig(raw) {
|
|
|
158
197
|
npmCdn
|
|
159
198
|
};
|
|
160
199
|
}
|
|
200
|
+
function validateLocale(locale) {
|
|
201
|
+
if (locale && /^[a-z]{2}_(?:[A-Z]{2}|[0-9]{3})$/.test(locale)) {
|
|
202
|
+
return locale;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
161
205
|
function validateWidgetConfig(raw) {
|
|
162
206
|
if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
|
|
163
207
|
if (!assertProp(raw, "user")) ; // TODO: This should be better type checked
|
|
164
208
|
|
|
165
209
|
return raw;
|
|
166
210
|
}
|
|
211
|
+
function validatePasswordlessConfig(raw) {
|
|
212
|
+
if (!isObject$1(raw)) throw new Error("Widget properties must be an object");
|
|
213
|
+
return raw;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const RENDER_WIDGET_QUERY = `
|
|
217
|
+
query renderWidget ($user: UserIdInput, $engagementMedium: UserEngagementMedium, $widgetType: WidgetType, $locale: RSLocale) {
|
|
218
|
+
renderWidget(user: $user, engagementMedium: $engagementMedium, widgetType: $widgetType, locale: $locale) {
|
|
219
|
+
template
|
|
220
|
+
user {
|
|
221
|
+
id
|
|
222
|
+
accountId
|
|
223
|
+
}
|
|
224
|
+
jsOptions
|
|
225
|
+
widgetConfig {
|
|
226
|
+
values
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
`;
|
|
167
231
|
|
|
168
232
|
/**
|
|
169
233
|
*
|
|
@@ -196,39 +260,6 @@ class WidgetApi {
|
|
|
196
260
|
this.domain = clean.domain;
|
|
197
261
|
this.npmCdn = clean.npmCdn;
|
|
198
262
|
}
|
|
199
|
-
/**
|
|
200
|
-
* Creates/upserts an anonymous user.
|
|
201
|
-
*
|
|
202
|
-
* @param {Object} params Parameters for request
|
|
203
|
-
* @param {WidgetType} params.widgetType The content of the widget.
|
|
204
|
-
* @param {EngagementMedium} params.engagementMedium How to display the widget.
|
|
205
|
-
* @param {CookieUser} params.user An optional user object
|
|
206
|
-
* @param {string} params.jwt the JSON Web Token (JWT) that is used to
|
|
207
|
-
* validate the data (can be disabled)
|
|
208
|
-
*
|
|
209
|
-
* @return {Promise} json object if true, with the widget template, jsOptions and user details.
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
cookieUser(params) {
|
|
214
|
-
// validateInput(params, CookieUserSchema);
|
|
215
|
-
const {
|
|
216
|
-
widgetType,
|
|
217
|
-
engagementMedium = "POPUP",
|
|
218
|
-
jwt,
|
|
219
|
-
user
|
|
220
|
-
} = params;
|
|
221
|
-
const tenantAlias = encodeURIComponent(this.tenantAlias);
|
|
222
|
-
|
|
223
|
-
const optionalParams = _buildParams({
|
|
224
|
-
widgetType,
|
|
225
|
-
engagementMedium
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
const path = `/api/v1/${tenantAlias}/widget/user/cookie_user${optionalParams}`;
|
|
229
|
-
const url = this.domain + path;
|
|
230
|
-
return doPut(url, JSON.stringify(user ? user : {}), jwt);
|
|
231
|
-
}
|
|
232
263
|
/**
|
|
233
264
|
* Creates/upserts user.
|
|
234
265
|
*
|
|
@@ -285,8 +316,10 @@ class WidgetApi {
|
|
|
285
316
|
|
|
286
317
|
|
|
287
318
|
render(params) {
|
|
319
|
+
var _clean$locale;
|
|
320
|
+
|
|
288
321
|
const raw = params;
|
|
289
|
-
const clean =
|
|
322
|
+
const clean = validatePasswordlessConfig(raw);
|
|
290
323
|
const {
|
|
291
324
|
widgetType,
|
|
292
325
|
engagementMedium = "POPUP",
|
|
@@ -294,17 +327,29 @@ class WidgetApi {
|
|
|
294
327
|
user
|
|
295
328
|
} = clean;
|
|
296
329
|
const tenantAlias = encodeURIComponent(this.tenantAlias);
|
|
297
|
-
const accountId = encodeURIComponent(user.accountId);
|
|
298
|
-
const userId = encodeURIComponent(user.id);
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
widgetType,
|
|
302
|
-
engagementMedium
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
const path = `/api/v1/${tenantAlias}/widget/account/${accountId}/user/${userId}/render${optionalParams}`;
|
|
330
|
+
const accountId = user ? encodeURIComponent(user.accountId) : null;
|
|
331
|
+
const userId = user ? encodeURIComponent(user.id) : null;
|
|
332
|
+
const locale = (_clean$locale = clean.locale) != null ? _clean$locale : validateLocale(navigator.language.replace(/\-/g, "_"));
|
|
333
|
+
const path = `/api/v1/${tenantAlias}/graphql`;
|
|
306
334
|
const url = this.domain + path;
|
|
307
|
-
return
|
|
335
|
+
return new Promise(async (resolve, reject) => {
|
|
336
|
+
try {
|
|
337
|
+
var _res$body, _res$body$data;
|
|
338
|
+
|
|
339
|
+
const res = await doQuery(url, RENDER_WIDGET_QUERY, {
|
|
340
|
+
user: userId && accountId ? {
|
|
341
|
+
id: userId,
|
|
342
|
+
accountId
|
|
343
|
+
} : null,
|
|
344
|
+
engagementMedium,
|
|
345
|
+
widgetType,
|
|
346
|
+
locale
|
|
347
|
+
}, jwt);
|
|
348
|
+
resolve(res == null ? void 0 : (_res$body = res.body) == null ? void 0 : (_res$body$data = _res$body.data) == null ? void 0 : _res$body$data.renderWidget);
|
|
349
|
+
} catch (e) {
|
|
350
|
+
reject(e);
|
|
351
|
+
}
|
|
352
|
+
});
|
|
308
353
|
}
|
|
309
354
|
/**
|
|
310
355
|
* An API call to send out referral invites to contacts
|
|
@@ -395,6 +440,7 @@ class AnalyticsApi {
|
|
|
395
440
|
}
|
|
396
441
|
|
|
397
442
|
pushAnalyticsLoadEvent(params) {
|
|
443
|
+
if (!params.externalUserId || !params.externalAccountId) return;
|
|
398
444
|
const tenantAlias = encodeURIComponent(params.tenantAlias);
|
|
399
445
|
const accountId = encodeURIComponent(params.externalAccountId);
|
|
400
446
|
const userId = encodeURIComponent(params.externalUserId);
|
|
@@ -421,7 +467,7 @@ class AnalyticsApi {
|
|
|
421
467
|
// @ts-check
|
|
422
468
|
/** @hidden */
|
|
423
469
|
|
|
424
|
-
const _log$
|
|
470
|
+
const _log$7 = debug__default("squatch-js:widget");
|
|
425
471
|
/*
|
|
426
472
|
* The Widget class is the base class for the different widget types available
|
|
427
473
|
*
|
|
@@ -434,7 +480,7 @@ const _log$6 = debug__default("squatch-js:widget");
|
|
|
434
480
|
|
|
435
481
|
class Widget {
|
|
436
482
|
constructor(params) {
|
|
437
|
-
_log$
|
|
483
|
+
_log$7("widget initializing ...");
|
|
438
484
|
|
|
439
485
|
this.content = params.content === "error" ? this._error(params.rsCode) : params.content;
|
|
440
486
|
this.type = params.type;
|
|
@@ -452,6 +498,8 @@ class Widget {
|
|
|
452
498
|
}
|
|
453
499
|
|
|
454
500
|
_loadEvent(sqh) {
|
|
501
|
+
var _this$analyticsApi$pu;
|
|
502
|
+
|
|
455
503
|
if (!sqh) return; // No non-truthy value
|
|
456
504
|
|
|
457
505
|
if (!isObject$1(sqh)) {
|
|
@@ -485,10 +533,10 @@ class Widget {
|
|
|
485
533
|
};
|
|
486
534
|
}
|
|
487
535
|
|
|
488
|
-
this.analyticsApi.pushAnalyticsLoadEvent(params).then(response => {
|
|
489
|
-
_log$
|
|
536
|
+
(_this$analyticsApi$pu = this.analyticsApi.pushAnalyticsLoadEvent(params)) == null ? void 0 : _this$analyticsApi$pu.then(response => {
|
|
537
|
+
_log$7(`${params.engagementMedium} loaded event recorded.`);
|
|
490
538
|
}).catch(ex => {
|
|
491
|
-
_log$
|
|
539
|
+
_log$7(new Error(`pushAnalyticsLoadEvent() ${ex}`));
|
|
492
540
|
});
|
|
493
541
|
}
|
|
494
542
|
|
|
@@ -501,9 +549,9 @@ class Widget {
|
|
|
501
549
|
engagementMedium: sqh.mode.widgetMode,
|
|
502
550
|
shareMedium: medium
|
|
503
551
|
}).then(response => {
|
|
504
|
-
_log$
|
|
552
|
+
_log$7(`${sqh.mode.widgetMode} share ${medium} event recorded. ${response}`);
|
|
505
553
|
}).catch(ex => {
|
|
506
|
-
_log$
|
|
554
|
+
_log$7(new Error(`pushAnalyticsLoadEvent() ${ex}`));
|
|
507
555
|
});
|
|
508
556
|
}
|
|
509
557
|
}
|
|
@@ -516,9 +564,9 @@ class Widget {
|
|
|
516
564
|
userId: sqh.analytics.attributes.userId,
|
|
517
565
|
emailList
|
|
518
566
|
}).then(response => {
|
|
519
|
-
_log$
|
|
567
|
+
_log$7(`Sent email invites to share ${emailList}. ${response}`);
|
|
520
568
|
}).catch(ex => {
|
|
521
|
-
_log$
|
|
569
|
+
_log$7(new Error(`invite() ${ex}`));
|
|
522
570
|
});
|
|
523
571
|
}
|
|
524
572
|
}
|
|
@@ -607,6 +655,7 @@ class Widget {
|
|
|
607
655
|
email: email || null,
|
|
608
656
|
firstName: firstName || null,
|
|
609
657
|
lastName: lastName || null,
|
|
658
|
+
// FIXME: Double check this
|
|
610
659
|
id: this.context.user.id,
|
|
611
660
|
accountId: this.context.user.accountId
|
|
612
661
|
};
|
|
@@ -616,17 +665,12 @@ class Widget {
|
|
|
616
665
|
widgetType: this.type,
|
|
617
666
|
jwt
|
|
618
667
|
});
|
|
619
|
-
} else if (this.context.type === "
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
firstName: firstName || null,
|
|
623
|
-
lastName: lastName || null
|
|
624
|
-
};
|
|
625
|
-
response = this.widgetApi.cookieUser({
|
|
626
|
-
user: userObj,
|
|
668
|
+
} else if (this.context.type === "passwordless") {
|
|
669
|
+
response = this.widgetApi.render({
|
|
670
|
+
user: undefined,
|
|
627
671
|
engagementMedium,
|
|
628
672
|
widgetType: this.type,
|
|
629
|
-
jwt
|
|
673
|
+
jwt: undefined
|
|
630
674
|
});
|
|
631
675
|
} else {
|
|
632
676
|
throw new Error("can't reload an error widget");
|
|
@@ -662,7 +706,7 @@ class Widget {
|
|
|
662
706
|
}).catch(({
|
|
663
707
|
message
|
|
664
708
|
}) => {
|
|
665
|
-
_log$
|
|
709
|
+
_log$7(`${message}`);
|
|
666
710
|
});
|
|
667
711
|
}
|
|
668
712
|
|
|
@@ -699,7 +743,7 @@ function domready(targetDoc, fn) {
|
|
|
699
743
|
|
|
700
744
|
// @ts-check
|
|
701
745
|
|
|
702
|
-
const _log$
|
|
746
|
+
const _log$6 = debug__default("squatch-js:EMBEDwidget");
|
|
703
747
|
/**
|
|
704
748
|
* An EmbedWidget is displayed inline in part of your page.
|
|
705
749
|
*
|
|
@@ -717,22 +761,22 @@ class EmbedWidget extends Widget {
|
|
|
717
761
|
// selector is a string
|
|
718
762
|
element = document.querySelector(container);
|
|
719
763
|
|
|
720
|
-
_log$
|
|
764
|
+
_log$6("loading widget with selector", element); // selector is an HTML element
|
|
721
765
|
|
|
722
766
|
} else if (container instanceof HTMLElement) {
|
|
723
767
|
element = container;
|
|
724
768
|
|
|
725
|
-
_log$
|
|
769
|
+
_log$6("loading widget with container", element); // garbage container found
|
|
726
770
|
|
|
727
771
|
} else if (container) {
|
|
728
772
|
element = null;
|
|
729
773
|
|
|
730
|
-
_log$
|
|
774
|
+
_log$6("container must be an HTMLElement or string", container); // find element on page
|
|
731
775
|
|
|
732
776
|
} else {
|
|
733
777
|
element = document.querySelector("#squatchembed") || document.querySelector(".squatchembed");
|
|
734
778
|
|
|
735
|
-
_log$
|
|
779
|
+
_log$6("loading widget with default selector", element);
|
|
736
780
|
}
|
|
737
781
|
|
|
738
782
|
if (!(element instanceof HTMLElement)) throw new Error(`element with selector '${container}' not found.'`);
|
|
@@ -798,7 +842,7 @@ class EmbedWidget extends Widget {
|
|
|
798
842
|
if (!this.context.container) {
|
|
799
843
|
this._loadEvent(_sqh);
|
|
800
844
|
|
|
801
|
-
_log$
|
|
845
|
+
_log$6("loaded");
|
|
802
846
|
}
|
|
803
847
|
});
|
|
804
848
|
} // Un-hide if element is available and refresh data
|
|
@@ -807,7 +851,7 @@ class EmbedWidget extends Widget {
|
|
|
807
851
|
open() {
|
|
808
852
|
var _this$frame, _this$frame$contentDo, _this$frame2, _this$frame2$contentW, _this$frame3, _this$frame3$contentW;
|
|
809
853
|
|
|
810
|
-
if (!this.frame) return _log$
|
|
854
|
+
if (!this.frame) return _log$6("no target element to open");
|
|
811
855
|
this.element.style.visibility = "unset";
|
|
812
856
|
this.element.style.height = "auto";
|
|
813
857
|
this.element.style["overflow-y"] = "auto";
|
|
@@ -817,16 +861,16 @@ class EmbedWidget extends Widget {
|
|
|
817
861
|
|
|
818
862
|
this._loadEvent(_sqh);
|
|
819
863
|
|
|
820
|
-
_log$
|
|
864
|
+
_log$6("loaded");
|
|
821
865
|
}
|
|
822
866
|
|
|
823
867
|
close() {
|
|
824
|
-
if (!this.frame) return _log$
|
|
868
|
+
if (!this.frame) return _log$6("no target element to close");
|
|
825
869
|
this.element.style.visibility = "hidden";
|
|
826
870
|
this.element.style.height = "0";
|
|
827
871
|
this.element.style["overflow-y"] = "hidden";
|
|
828
872
|
|
|
829
|
-
_log$
|
|
873
|
+
_log$6("Embed widget closed");
|
|
830
874
|
}
|
|
831
875
|
|
|
832
876
|
_error(rs, mode = "embed", style = "") {
|
|
@@ -837,7 +881,7 @@ class EmbedWidget extends Widget {
|
|
|
837
881
|
|
|
838
882
|
// @ts-check
|
|
839
883
|
|
|
840
|
-
const _log$
|
|
884
|
+
const _log$5 = debug__default("squatch-js:POPUPwidget");
|
|
841
885
|
/**
|
|
842
886
|
* The PopupWidget is used to display popups (also known as "Modals").
|
|
843
887
|
* Popups widgets are rendered on top of other elements in a page.
|
|
@@ -855,9 +899,9 @@ class PopupWidget extends Widget {
|
|
|
855
899
|
this.triggerElement
|
|
856
900
|
/* HTMLButton */
|
|
857
901
|
= document.querySelector(trigger);
|
|
858
|
-
if (trigger && !this.triggerElement) _log$
|
|
902
|
+
if (trigger && !this.triggerElement) _log$5("No element found with trigger selector", trigger);
|
|
859
903
|
} catch (_unused) {
|
|
860
|
-
_log$
|
|
904
|
+
_log$5("Not a valid selector", trigger);
|
|
861
905
|
} // Trigger is optional
|
|
862
906
|
|
|
863
907
|
|
|
@@ -880,6 +924,7 @@ class PopupWidget extends Widget {
|
|
|
880
924
|
this.popupdiv = document.createElement("div");
|
|
881
925
|
this.popupdiv.id = "squatchModal";
|
|
882
926
|
this.popupdiv.setAttribute("style", "display: none; position: fixed; z-index: 1; padding-top: 5%; left: 0; top: -2000px; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.4);");
|
|
927
|
+
document.head.insertAdjacentHTML("beforeend", `<style>#squatchModal::-webkit-scrollbar { display: none; }</style>`);
|
|
883
928
|
this.popupcontent = document.createElement("div");
|
|
884
929
|
this.popupcontent.setAttribute("style", "margin: auto; width: 80%; max-width: 500px; position: relative;");
|
|
885
930
|
|
|
@@ -899,7 +944,7 @@ class PopupWidget extends Widget {
|
|
|
899
944
|
frameDoc.write(`<script src="${this.npmCdn}/resize-observer-polyfill@1.5.x"></script>`);
|
|
900
945
|
frameDoc.close();
|
|
901
946
|
|
|
902
|
-
_log$
|
|
947
|
+
_log$5("Popup template loaded into iframe");
|
|
903
948
|
|
|
904
949
|
this._setupResizeHandler();
|
|
905
950
|
}
|
|
@@ -972,7 +1017,7 @@ class PopupWidget extends Widget {
|
|
|
972
1017
|
|
|
973
1018
|
this._loadEvent(_sqh);
|
|
974
1019
|
|
|
975
|
-
_log$
|
|
1020
|
+
_log$5("Popup opened");
|
|
976
1021
|
});
|
|
977
1022
|
}
|
|
978
1023
|
|
|
@@ -980,7 +1025,7 @@ class PopupWidget extends Widget {
|
|
|
980
1025
|
this.popupdiv.style.visibility = "hidden";
|
|
981
1026
|
this.popupdiv.style.top = "-2000px";
|
|
982
1027
|
|
|
983
|
-
_log$
|
|
1028
|
+
_log$5("Popup closed");
|
|
984
1029
|
}
|
|
985
1030
|
|
|
986
1031
|
_clickedOutside({
|
|
@@ -998,7 +1043,7 @@ class PopupWidget extends Widget {
|
|
|
998
1043
|
|
|
999
1044
|
}
|
|
1000
1045
|
|
|
1001
|
-
const _log$
|
|
1046
|
+
const _log$4 = debug("squatch-js:CTAwidget");
|
|
1002
1047
|
/**
|
|
1003
1048
|
* A CtaWidget is displayed on top of your page
|
|
1004
1049
|
*
|
|
@@ -1009,7 +1054,7 @@ const _log$3 = debug("squatch-js:CTAwidget");
|
|
|
1009
1054
|
|
|
1010
1055
|
class CtaWidget extends PopupWidget {
|
|
1011
1056
|
constructor(params, opts) {
|
|
1012
|
-
_log$
|
|
1057
|
+
_log$4("CTA constructor");
|
|
1013
1058
|
|
|
1014
1059
|
const ctaElement = document.createElement("div");
|
|
1015
1060
|
ctaElement.id = "cta";
|
|
@@ -1037,7 +1082,7 @@ class CtaWidget extends PopupWidget {
|
|
|
1037
1082
|
this.ctaFrame.setAttribute("style", `border:0; background-color:transparent; position:fixed; display:none;${this.side}${this.position}`);
|
|
1038
1083
|
document.body.appendChild(this.ctaFrame);
|
|
1039
1084
|
|
|
1040
|
-
_log$
|
|
1085
|
+
_log$4("ctaframe appended to body");
|
|
1041
1086
|
}
|
|
1042
1087
|
|
|
1043
1088
|
load() {
|
|
@@ -1101,10 +1146,10 @@ class CtaWidget extends PopupWidget {
|
|
|
1101
1146
|
});
|
|
1102
1147
|
ro.observe(ctaContainer);
|
|
1103
1148
|
|
|
1104
|
-
_log$
|
|
1149
|
+
_log$4("CTA template loaded into iframe");
|
|
1105
1150
|
});
|
|
1106
1151
|
} else {
|
|
1107
|
-
_log$
|
|
1152
|
+
_log$4(new Error("CTA element not found in theme"));
|
|
1108
1153
|
}
|
|
1109
1154
|
});
|
|
1110
1155
|
}
|
|
@@ -1127,7 +1172,7 @@ class CtaWidget extends PopupWidget {
|
|
|
1127
1172
|
|
|
1128
1173
|
}
|
|
1129
1174
|
|
|
1130
|
-
const _log$
|
|
1175
|
+
const _log$3 = debug__default("squatch-js:widgets");
|
|
1131
1176
|
/**
|
|
1132
1177
|
*
|
|
1133
1178
|
* `Widgets` is a factory for creating widgets. It's possible to build your own widgets using the
|
|
@@ -1165,41 +1210,6 @@ class Widgets {
|
|
|
1165
1210
|
|
|
1166
1211
|
EventBus.addEventListener("submit_email", Widgets._cb);
|
|
1167
1212
|
}
|
|
1168
|
-
/**
|
|
1169
|
-
* This function calls the {@link WidgetApi.cookieUser} method, and it renders
|
|
1170
|
-
* the widget if it is successful. Otherwise it shows the "error" widget.
|
|
1171
|
-
*
|
|
1172
|
-
* @param {Object} config Config details
|
|
1173
|
-
* @param {WidgetType} config.widgetType The content of the widget.
|
|
1174
|
-
* @param {EngagementMedium} config.engagementMedium How to display the widget.
|
|
1175
|
-
* @param {User} config.user An optional user to include
|
|
1176
|
-
* @param {string} config.jwt the JSON Web Token (JWT) that is used to
|
|
1177
|
-
* validate the data (can be disabled)
|
|
1178
|
-
*
|
|
1179
|
-
* @return {Promise<WidgetResult>} json object if true, with a Widget and user details.
|
|
1180
|
-
*/
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
async createCookieUser(config) {
|
|
1184
|
-
try {
|
|
1185
|
-
const response = await this.api.cookieUser(config);
|
|
1186
|
-
return {
|
|
1187
|
-
widget: this._renderWidget(response, config, {
|
|
1188
|
-
type: "cookie",
|
|
1189
|
-
engagementMedium: config.engagementMedium
|
|
1190
|
-
}),
|
|
1191
|
-
user: response.user
|
|
1192
|
-
};
|
|
1193
|
-
} catch (err) {
|
|
1194
|
-
_log$2(err);
|
|
1195
|
-
|
|
1196
|
-
if (err.apiErrorCode) {
|
|
1197
|
-
this._renderErrorWidget(err, config.engagementMedium);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
throw err;
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
1213
|
/**
|
|
1204
1214
|
* This function calls the {@link WidgetApi.upsertUser} method, and it renders
|
|
1205
1215
|
* the widget if it is successful. Otherwise it shows the "error" widget.
|
|
@@ -1227,7 +1237,7 @@ class Widgets {
|
|
|
1227
1237
|
return {
|
|
1228
1238
|
widget: this._renderWidget(response, clean, {
|
|
1229
1239
|
type: "upsert",
|
|
1230
|
-
user: clean.user,
|
|
1240
|
+
user: clean.user || null,
|
|
1231
1241
|
engagementMedium: config.engagementMedium,
|
|
1232
1242
|
container: config.container,
|
|
1233
1243
|
trigger: config.trigger
|
|
@@ -1235,7 +1245,7 @@ class Widgets {
|
|
|
1235
1245
|
user: response.user
|
|
1236
1246
|
};
|
|
1237
1247
|
} catch (err) {
|
|
1238
|
-
_log$
|
|
1248
|
+
_log$3(err);
|
|
1239
1249
|
|
|
1240
1250
|
if (err.apiErrorCode) {
|
|
1241
1251
|
this._renderErrorWidget(err, config.engagementMedium);
|
|
@@ -1263,15 +1273,13 @@ class Widgets {
|
|
|
1263
1273
|
|
|
1264
1274
|
async render(config) {
|
|
1265
1275
|
const raw = config;
|
|
1266
|
-
const clean =
|
|
1276
|
+
const clean = validatePasswordlessConfig(raw);
|
|
1267
1277
|
|
|
1268
1278
|
try {
|
|
1269
|
-
const response = await this.api.
|
|
1279
|
+
const response = await this.api.render(clean);
|
|
1270
1280
|
return {
|
|
1271
|
-
widget: this._renderWidget({
|
|
1272
|
-
|
|
1273
|
-
}, clean, {
|
|
1274
|
-
type: "cookie",
|
|
1281
|
+
widget: this._renderWidget(response, clean, {
|
|
1282
|
+
type: "passwordless",
|
|
1275
1283
|
engagementMedium: clean.engagementMedium
|
|
1276
1284
|
}),
|
|
1277
1285
|
user: response.user
|
|
@@ -1298,7 +1306,7 @@ class Widgets {
|
|
|
1298
1306
|
|
|
1299
1307
|
if (typeof input === "function") {
|
|
1300
1308
|
this.api.squatchReferralCookie().then((...args) => input(...args)).catch(ex => {
|
|
1301
|
-
_log$
|
|
1309
|
+
_log$3("Autofill error", ex);
|
|
1302
1310
|
|
|
1303
1311
|
throw ex;
|
|
1304
1312
|
});
|
|
@@ -1313,7 +1321,7 @@ class Widgets {
|
|
|
1313
1321
|
// Only use the first element found
|
|
1314
1322
|
elem = elems[0];
|
|
1315
1323
|
} else {
|
|
1316
|
-
_log$
|
|
1324
|
+
_log$3("Element id/class or function missing");
|
|
1317
1325
|
|
|
1318
1326
|
throw new Error("Element id/class or function missing");
|
|
1319
1327
|
}
|
|
@@ -1351,11 +1359,11 @@ class Widgets {
|
|
|
1351
1359
|
|
|
1352
1360
|
|
|
1353
1361
|
_renderWidget(response, config, context) {
|
|
1354
|
-
_log$
|
|
1362
|
+
_log$3("Rendering Widget...");
|
|
1355
1363
|
|
|
1356
1364
|
if (!response) throw new Error("Unable to get a response");
|
|
1357
1365
|
let widget;
|
|
1358
|
-
let displayOnLoad =
|
|
1366
|
+
let displayOnLoad = !!config.displayOnLoad;
|
|
1359
1367
|
let displayCTA = false;
|
|
1360
1368
|
const opts = response.jsOptions || "";
|
|
1361
1369
|
const params = {
|
|
@@ -1374,9 +1382,9 @@ class Widgets {
|
|
|
1374
1382
|
displayOnLoad = rule.displayOnLoad;
|
|
1375
1383
|
displayCTA = rule.showAsCTA;
|
|
1376
1384
|
|
|
1377
|
-
_log$
|
|
1385
|
+
_log$3(`Display ${rule.widgetType} on ${rule.url}`);
|
|
1378
1386
|
} else {
|
|
1379
|
-
_log$
|
|
1387
|
+
_log$3(`Don't display ${rule.widgetType} when no referral on widget rule match ${rule.url}`);
|
|
1380
1388
|
}
|
|
1381
1389
|
}
|
|
1382
1390
|
});
|
|
@@ -1385,20 +1393,20 @@ class Widgets {
|
|
|
1385
1393
|
if (opts.conversionUrls) {
|
|
1386
1394
|
opts.conversionUrls.forEach(rule => {
|
|
1387
1395
|
if (response.user.referredBy && Widgets._matchesUrl(rule)) {
|
|
1388
|
-
_log$
|
|
1396
|
+
_log$3("This is a conversion URL", rule);
|
|
1389
1397
|
}
|
|
1390
1398
|
});
|
|
1391
1399
|
}
|
|
1392
1400
|
|
|
1393
1401
|
if (opts.fuelTankAutofillUrls) {
|
|
1394
|
-
_log$
|
|
1402
|
+
_log$3("We found a fuel tank autofill!");
|
|
1395
1403
|
|
|
1396
1404
|
opts.fuelTankAutofillUrls.forEach(({
|
|
1397
1405
|
url,
|
|
1398
1406
|
formSelector
|
|
1399
1407
|
}) => {
|
|
1400
1408
|
if (Widgets._matchesUrl(url)) {
|
|
1401
|
-
_log$
|
|
1409
|
+
_log$3("Fuel Tank URL matches");
|
|
1402
1410
|
|
|
1403
1411
|
if (response.user.referredBy && response.user.referredBy.code) {
|
|
1404
1412
|
const formAutofill = document.querySelector(formSelector);
|
|
@@ -1406,7 +1414,7 @@ class Widgets {
|
|
|
1406
1414
|
if (formAutofill) {
|
|
1407
1415
|
formAutofill.value = response.user.referredBy.referredReward.fuelTankCode || "";
|
|
1408
1416
|
} else {
|
|
1409
|
-
_log$
|
|
1417
|
+
_log$3(new Error(`Element with id/class ${formSelector} was not found.`));
|
|
1410
1418
|
}
|
|
1411
1419
|
}
|
|
1412
1420
|
}
|
|
@@ -1421,7 +1429,7 @@ class Widgets {
|
|
|
1421
1429
|
widget.load();
|
|
1422
1430
|
if (displayOnLoad) widget.open();
|
|
1423
1431
|
} else if (displayCTA) {
|
|
1424
|
-
_log$
|
|
1432
|
+
_log$3("display CTA");
|
|
1425
1433
|
|
|
1426
1434
|
const side = opts.cta.content.buttonSide;
|
|
1427
1435
|
const position = opts.cta.content.buttonPosition;
|
|
@@ -1432,7 +1440,7 @@ class Widgets {
|
|
|
1432
1440
|
widget.load();
|
|
1433
1441
|
if (displayOnLoad) widget.open();
|
|
1434
1442
|
} else {
|
|
1435
|
-
_log$
|
|
1443
|
+
_log$3("display popup on load");
|
|
1436
1444
|
|
|
1437
1445
|
widget = new PopupWidget(params);
|
|
1438
1446
|
widget.load();
|
|
@@ -1456,7 +1464,7 @@ class Widgets {
|
|
|
1456
1464
|
message
|
|
1457
1465
|
} = props;
|
|
1458
1466
|
|
|
1459
|
-
_log$
|
|
1467
|
+
_log$3(new Error(`${apiErrorCode} (${rsCode}) ${message}`));
|
|
1460
1468
|
|
|
1461
1469
|
const params = {
|
|
1462
1470
|
content: "error",
|
|
@@ -1596,7 +1604,8 @@ function asyncLoad() {
|
|
|
1596
1604
|
|
|
1597
1605
|
if (loaded && cached) {
|
|
1598
1606
|
const ready = cached.ready || [];
|
|
1599
|
-
ready.forEach(cb => setTimeout(() => cb(), 0));
|
|
1607
|
+
ready.forEach(cb => setTimeout(() => cb(), 0));
|
|
1608
|
+
setTimeout(() => window.squatch._auto(), 0); // @ts-ignore -- intetionally deletes `_squatch` to cleanup initialization
|
|
1600
1609
|
|
|
1601
1610
|
window._squatch = undefined;
|
|
1602
1611
|
|
|
@@ -1986,7 +1995,7 @@ var URLSearchParams$1 = self.URLSearchParams;
|
|
|
1986
1995
|
|
|
1987
1996
|
/** @hidden */
|
|
1988
1997
|
|
|
1989
|
-
const _log$
|
|
1998
|
+
const _log$2 = debug__default("squatch-js");
|
|
1990
1999
|
|
|
1991
2000
|
const isObject = item => typeof item === "object" && !Array.isArray(item);
|
|
1992
2001
|
|
|
@@ -2039,7 +2048,7 @@ function _pushCookie() {
|
|
|
2039
2048
|
try {
|
|
2040
2049
|
paramsJSON = JSON.parse(b64decode(refParam));
|
|
2041
2050
|
} catch (error) {
|
|
2042
|
-
_log$
|
|
2051
|
+
_log$2("Unable to decode params", error); // don't merge invalid params
|
|
2043
2052
|
|
|
2044
2053
|
|
|
2045
2054
|
return;
|
|
@@ -2048,26 +2057,26 @@ function _pushCookie() {
|
|
|
2048
2057
|
try {
|
|
2049
2058
|
existingCookie = JSON.parse(b64decode(Cookies.get("_saasquatch")));
|
|
2050
2059
|
|
|
2051
|
-
_log$
|
|
2060
|
+
_log$2("existing cookie", existingCookie);
|
|
2052
2061
|
} catch (error) {
|
|
2053
|
-
_log$
|
|
2062
|
+
_log$2("Unable to retrieve cookie", error);
|
|
2054
2063
|
} // don't merge if there's no existing object
|
|
2055
2064
|
|
|
2056
2065
|
|
|
2057
2066
|
try {
|
|
2058
2067
|
const domain = getTopDomain();
|
|
2059
2068
|
|
|
2060
|
-
_log$
|
|
2069
|
+
_log$2("domain retrieved:", domain);
|
|
2061
2070
|
|
|
2062
2071
|
if (existingCookie) {
|
|
2063
2072
|
const newCookie = deepMerge(existingCookie, paramsJSON);
|
|
2064
2073
|
reEncodedCookie = b64encode(JSON.stringify(newCookie));
|
|
2065
2074
|
|
|
2066
|
-
_log$
|
|
2075
|
+
_log$2("cookie to store:", newCookie);
|
|
2067
2076
|
} else {
|
|
2068
2077
|
reEncodedCookie = b64encode(JSON.stringify(paramsJSON));
|
|
2069
2078
|
|
|
2070
|
-
_log$
|
|
2079
|
+
_log$2("cookie to store:", paramsJSON);
|
|
2071
2080
|
}
|
|
2072
2081
|
|
|
2073
2082
|
Cookies.set("_saasquatch", reEncodedCookie, {
|
|
@@ -2078,11 +2087,86 @@ function _pushCookie() {
|
|
|
2078
2087
|
path: "/"
|
|
2079
2088
|
});
|
|
2080
2089
|
} catch (error) {
|
|
2081
|
-
_log$
|
|
2090
|
+
_log$2("Unable to set cookie", error);
|
|
2082
2091
|
}
|
|
2083
2092
|
}
|
|
2084
2093
|
}
|
|
2085
2094
|
|
|
2095
|
+
/** @hidden */
|
|
2096
|
+
|
|
2097
|
+
const _log$1 = debug__default("squatch-js");
|
|
2098
|
+
|
|
2099
|
+
function _getAutoConfig(configIn) {
|
|
2100
|
+
const queryString = window.location.search;
|
|
2101
|
+
const urlParams = new URLSearchParams(queryString);
|
|
2102
|
+
const refParam = urlParams.get("_saasquatchExtra") || "";
|
|
2103
|
+
|
|
2104
|
+
if (!refParam) {
|
|
2105
|
+
_log$1("No _saasquatchExtra param");
|
|
2106
|
+
|
|
2107
|
+
return;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
let raw;
|
|
2111
|
+
|
|
2112
|
+
try {
|
|
2113
|
+
raw = JSON.parse(b64decode(refParam));
|
|
2114
|
+
} catch (e) {
|
|
2115
|
+
_log$1("Unable to decode _saasquatchExtra config");
|
|
2116
|
+
|
|
2117
|
+
return;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
const {
|
|
2121
|
+
domain,
|
|
2122
|
+
tenantAlias,
|
|
2123
|
+
widgetConfig
|
|
2124
|
+
} = convertExtraToConfig(raw);
|
|
2125
|
+
|
|
2126
|
+
if (!domain || !tenantAlias || !widgetConfig) {
|
|
2127
|
+
_log$1("_saasquatchExtra did not have an expected structure");
|
|
2128
|
+
|
|
2129
|
+
return undefined;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
const {
|
|
2133
|
+
autoPopupWidgetType
|
|
2134
|
+
} = widgetConfig,
|
|
2135
|
+
rest = _objectWithoutPropertiesLoose(widgetConfig, ["autoPopupWidgetType"]);
|
|
2136
|
+
|
|
2137
|
+
return {
|
|
2138
|
+
widgetConfig: _extends({
|
|
2139
|
+
widgetType: autoPopupWidgetType,
|
|
2140
|
+
displayOnLoad: true
|
|
2141
|
+
}, rest),
|
|
2142
|
+
squatchConfig: _extends({}, configIn ? {
|
|
2143
|
+
configIn
|
|
2144
|
+
} : {}, {
|
|
2145
|
+
domain,
|
|
2146
|
+
tenantAlias
|
|
2147
|
+
})
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Deconstructs _saasquatchExtra into domain, tenantAlias, and widgetConfig
|
|
2152
|
+
* @param obj {Record<string, any>} Expected to be of the form `{ [appDomain]: { [tenantAlias]: { autoPopupWidgetType: [widgetType], [rest]?: ... } } }`
|
|
2153
|
+
*/
|
|
2154
|
+
|
|
2155
|
+
function convertExtraToConfig(obj) {
|
|
2156
|
+
var _obj$_domain;
|
|
2157
|
+
|
|
2158
|
+
const _domain = Object.keys(obj || {})[0];
|
|
2159
|
+
const tenantAlias = Object.keys((obj == null ? void 0 : obj[_domain]) || {})[0];
|
|
2160
|
+
const widgetConfig = obj == null ? void 0 : (_obj$_domain = obj[_domain]) == null ? void 0 : _obj$_domain[tenantAlias]; // domain in _saasquatchExtra doesn't contain "https://"
|
|
2161
|
+
|
|
2162
|
+
const domain = _domain ? `https://${_domain}` : undefined;
|
|
2163
|
+
return {
|
|
2164
|
+
domain,
|
|
2165
|
+
tenantAlias,
|
|
2166
|
+
widgetConfig
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2086
2170
|
// @ts-check
|
|
2087
2171
|
function help() {
|
|
2088
2172
|
console.log(`Having trouble using Squatch.js? Go to https://docs.referralsaasquatch.com/developer/ for tutorials, references and error codes.`);
|
|
@@ -2136,6 +2220,33 @@ function widgets() {
|
|
|
2136
2220
|
function events() {
|
|
2137
2221
|
return _events;
|
|
2138
2222
|
}
|
|
2223
|
+
/**
|
|
2224
|
+
* Entry-point for high level API to render a widget using the instance of {@link Widgets} created when you call {@link #init init}.
|
|
2225
|
+
*/
|
|
2226
|
+
|
|
2227
|
+
function widget(widgetConfig) {
|
|
2228
|
+
var _widgets2;
|
|
2229
|
+
|
|
2230
|
+
return (_widgets2 = widgets()) == null ? void 0 : _widgets2.render(widgetConfig);
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Extracts widget configuration from `_saasquatchExtra` UTM parameter. Initialises `squatch` and renders the widget as a {@link PopupWidget} via static instanct of {@link Widgets}.
|
|
2234
|
+
*/
|
|
2235
|
+
|
|
2236
|
+
function _auto(configIn) {
|
|
2237
|
+
const configs = _getAutoConfig(configIn);
|
|
2238
|
+
|
|
2239
|
+
if (configs) {
|
|
2240
|
+
var _widgets3;
|
|
2241
|
+
|
|
2242
|
+
const {
|
|
2243
|
+
squatchConfig,
|
|
2244
|
+
widgetConfig
|
|
2245
|
+
} = configs;
|
|
2246
|
+
init(squatchConfig);
|
|
2247
|
+
return (_widgets3 = widgets()) == null ? void 0 : _widgets3.render(widgetConfig);
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2139
2250
|
/**
|
|
2140
2251
|
* Initializes the static `squatch` global. This sets up:
|
|
2141
2252
|
*
|
|
@@ -2178,7 +2289,7 @@ function init(configIn) {
|
|
|
2178
2289
|
* @example
|
|
2179
2290
|
* squatch.ready(function() {
|
|
2180
2291
|
* console.log("ready!");
|
|
2181
|
-
* squatch.api().
|
|
2292
|
+
* squatch.api().upsertUser();
|
|
2182
2293
|
* });
|
|
2183
2294
|
*/
|
|
2184
2295
|
|
|
@@ -2240,5 +2351,5 @@ if (typeof document !== "undefined" && !window.SaaSquatchDoNotAutoDrop) {
|
|
|
2240
2351
|
|
|
2241
2352
|
if (typeof document !== "undefined") asyncLoad();
|
|
2242
2353
|
|
|
2243
|
-
export { CtaWidget, EmbedWidget, PopupWidget, WidgetApi, Widgets, api, autofill, events, help, init, pushCookie, ready, submitEmail, widgets };
|
|
2354
|
+
export { CtaWidget, EmbedWidget, PopupWidget, WidgetApi, Widgets, _auto, api, autofill, events, help, init, pushCookie, ready, submitEmail, widget, widgets };
|
|
2244
2355
|
//# sourceMappingURL=squatch.esm.js.map
|