saasco-sdk 0.2.4 → 0.2.5
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/README.md +974 -0
- package/dist/index.cjs +168 -117
- package/dist/index.d.cts +21 -42
- package/dist/index.d.ts +21 -42
- package/dist/index.js +168 -117
- package/dist/support.cjs +1411 -829
- package/dist/support.d.cts +20 -9
- package/dist/support.d.ts +20 -9
- package/dist/support.js +1439 -857
- package/package.json +21 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { isValid, parse } from "psl";
|
|
3
3
|
|
|
4
4
|
// package.json
|
|
5
|
-
var version = "0.2.
|
|
5
|
+
var version = "0.2.5";
|
|
6
6
|
|
|
7
7
|
// src/lib/timezones.ts
|
|
8
8
|
var timezones = {
|
|
@@ -451,6 +451,9 @@ var AnalyticsLogger = class {
|
|
|
451
451
|
constructor(config) {
|
|
452
452
|
this.config = config;
|
|
453
453
|
}
|
|
454
|
+
setLevel(level) {
|
|
455
|
+
this.config.level = level;
|
|
456
|
+
}
|
|
454
457
|
debug(...args) {
|
|
455
458
|
if (this.config.level < 3 /* DEBUG */) {
|
|
456
459
|
return;
|
|
@@ -531,9 +534,34 @@ function getIntegrationLoggerLevel(integrationName, debug) {
|
|
|
531
534
|
}
|
|
532
535
|
|
|
533
536
|
// src/lib/utils/uuid.ts
|
|
534
|
-
|
|
537
|
+
var HEX = [];
|
|
538
|
+
for (let i = 0; i < 256; i++) {
|
|
539
|
+
HEX[i] = (i + 256).toString(16).slice(1);
|
|
540
|
+
}
|
|
535
541
|
function uuid() {
|
|
536
|
-
|
|
542
|
+
const bytes = randomBytes(16);
|
|
543
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
544
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
545
|
+
let out = "";
|
|
546
|
+
for (let i = 0; i < 16; i++) {
|
|
547
|
+
out += HEX[bytes[i]];
|
|
548
|
+
if (i === 3 || i === 5 || i === 7 || i === 9) {
|
|
549
|
+
out += "-";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
return out;
|
|
553
|
+
}
|
|
554
|
+
function randomBytes(length) {
|
|
555
|
+
const bytes = new Uint8Array(length);
|
|
556
|
+
const webCrypto = globalThis.crypto;
|
|
557
|
+
if (typeof webCrypto?.getRandomValues === "function") {
|
|
558
|
+
webCrypto.getRandomValues(bytes);
|
|
559
|
+
return bytes;
|
|
560
|
+
}
|
|
561
|
+
for (let i = 0; i < length; i++) {
|
|
562
|
+
bytes[i] = Math.random() * 256 | 0;
|
|
563
|
+
}
|
|
564
|
+
return bytes;
|
|
537
565
|
}
|
|
538
566
|
|
|
539
567
|
// src/lib/getBrowserContext.ts
|
|
@@ -1839,6 +1867,41 @@ function normalizeSaascoUrl(url) {
|
|
|
1839
1867
|
return parsed.toString();
|
|
1840
1868
|
}
|
|
1841
1869
|
|
|
1870
|
+
// src/lib/widgetLoader.ts
|
|
1871
|
+
function isEnabledPayload(data2) {
|
|
1872
|
+
return typeof data2 === "object" && data2 !== null && "enabled" in data2 && data2.enabled === true;
|
|
1873
|
+
}
|
|
1874
|
+
function getUrlOrigin(url) {
|
|
1875
|
+
try {
|
|
1876
|
+
return new URL(
|
|
1877
|
+
url,
|
|
1878
|
+
typeof window === "undefined" ? void 0 : window.location.href
|
|
1879
|
+
).origin;
|
|
1880
|
+
} catch {
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
function isLoaderPresent(fileName, injectedFlag) {
|
|
1884
|
+
return Boolean(
|
|
1885
|
+
injectedFlag || document.querySelector(`script[src*="${fileName}"]`)
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
function appendLoaderScript({
|
|
1889
|
+
attributes,
|
|
1890
|
+
onLoad,
|
|
1891
|
+
src
|
|
1892
|
+
}) {
|
|
1893
|
+
const script = document.createElement("script");
|
|
1894
|
+
script.async = true;
|
|
1895
|
+
script.src = src;
|
|
1896
|
+
for (const [name, value] of Object.entries(attributes)) {
|
|
1897
|
+
script.setAttribute(name, value);
|
|
1898
|
+
}
|
|
1899
|
+
if (onLoad) {
|
|
1900
|
+
script.addEventListener("load", onLoad);
|
|
1901
|
+
}
|
|
1902
|
+
(document.body ?? document.head ?? document.documentElement).append(script);
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1842
1905
|
// src/lib/social-proof/storage.ts
|
|
1843
1906
|
var WIDGET_PAYLOAD_PATH = "/api/social-proof/widget";
|
|
1844
1907
|
var SOCIAL_PROOF_LOADER_FILE = "saasco-social-proof-loader.js";
|
|
@@ -1918,17 +1981,16 @@ async function injectSocialProofLoader({
|
|
|
1918
1981
|
return;
|
|
1919
1982
|
}
|
|
1920
1983
|
window.__saascoSocialProofInjected = true;
|
|
1921
|
-
const
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
script.setAttribute("data-projectId", projectId);
|
|
1984
|
+
const attributes = {
|
|
1985
|
+
"data-projectId": projectId
|
|
1986
|
+
};
|
|
1925
1987
|
if (baseUrlOverride !== void 0) {
|
|
1926
|
-
|
|
1927
|
-
"data-base-url",
|
|
1928
|
-
normalizeSaascoBaseUrl(baseUrlOverride)
|
|
1929
|
-
);
|
|
1988
|
+
attributes["data-base-url"] = normalizeSaascoBaseUrl(baseUrlOverride);
|
|
1930
1989
|
}
|
|
1931
|
-
(
|
|
1990
|
+
appendLoaderScript({
|
|
1991
|
+
attributes,
|
|
1992
|
+
src: normalizeSaascoUrl(scriptUrl)
|
|
1993
|
+
});
|
|
1932
1994
|
}
|
|
1933
1995
|
async function shouldInjectSocialProof({
|
|
1934
1996
|
baseUrl,
|
|
@@ -1957,23 +2019,12 @@ async function shouldInjectSocialProof({
|
|
|
1957
2019
|
writeSession(cacheKey, JSON.stringify({ data: data2, fetchedAt: Date.now() }));
|
|
1958
2020
|
return isEnabledPayload(data2);
|
|
1959
2021
|
}
|
|
1960
|
-
function isEnabledPayload(data2) {
|
|
1961
|
-
return typeof data2 === "object" && data2 !== null && data2.enabled === true;
|
|
1962
|
-
}
|
|
1963
2022
|
function isSocialProofLoaderPresent() {
|
|
1964
|
-
return
|
|
1965
|
-
|
|
2023
|
+
return isLoaderPresent(
|
|
2024
|
+
SOCIAL_PROOF_LOADER_FILE,
|
|
2025
|
+
window.__saascoSocialProofInjected
|
|
1966
2026
|
);
|
|
1967
2027
|
}
|
|
1968
|
-
function getUrlOrigin(url) {
|
|
1969
|
-
try {
|
|
1970
|
-
return new URL(
|
|
1971
|
-
url,
|
|
1972
|
-
typeof window === "undefined" ? void 0 : window.location.href
|
|
1973
|
-
).origin;
|
|
1974
|
-
} catch {
|
|
1975
|
-
}
|
|
1976
|
-
}
|
|
1977
2028
|
function isSocialProofQaMode() {
|
|
1978
2029
|
if (typeof window === "undefined") {
|
|
1979
2030
|
return false;
|
|
@@ -1988,6 +2039,72 @@ function isSocialProofQaMode() {
|
|
|
1988
2039
|
}
|
|
1989
2040
|
}
|
|
1990
2041
|
|
|
2042
|
+
// src/lib/support/widgetEnabledCheck.ts
|
|
2043
|
+
var SUPPORT_WIDGET_PATH = "/api/support/widget";
|
|
2044
|
+
var SUPPORT_LOADER_FILE = "saasco-support-loader.js";
|
|
2045
|
+
async function injectSupportLoader({
|
|
2046
|
+
baseUrl: baseUrlOverride,
|
|
2047
|
+
onLoad,
|
|
2048
|
+
placeholder,
|
|
2049
|
+
projectId,
|
|
2050
|
+
scriptUrl
|
|
2051
|
+
}) {
|
|
2052
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
2053
|
+
return "skipped";
|
|
2054
|
+
}
|
|
2055
|
+
if (isSupportLoaderPresent()) {
|
|
2056
|
+
return "present";
|
|
2057
|
+
}
|
|
2058
|
+
const baseUrl = normalizeSaascoBaseUrl(
|
|
2059
|
+
baseUrlOverride ?? getUrlOrigin(scriptUrl) ?? SAASCO_ORIGIN
|
|
2060
|
+
);
|
|
2061
|
+
const enabled = await shouldInjectSupport({
|
|
2062
|
+
baseUrl,
|
|
2063
|
+
projectId
|
|
2064
|
+
});
|
|
2065
|
+
if (!enabled) {
|
|
2066
|
+
return "skipped";
|
|
2067
|
+
}
|
|
2068
|
+
if (isSupportLoaderPresent()) {
|
|
2069
|
+
return "present";
|
|
2070
|
+
}
|
|
2071
|
+
window.__saascoSupportInjected = true;
|
|
2072
|
+
const attributes = {
|
|
2073
|
+
"data-projectId": projectId
|
|
2074
|
+
};
|
|
2075
|
+
if (baseUrlOverride !== void 0) {
|
|
2076
|
+
attributes["data-base-url"] = normalizeSaascoBaseUrl(baseUrlOverride);
|
|
2077
|
+
}
|
|
2078
|
+
if (placeholder !== void 0) {
|
|
2079
|
+
attributes["data-placeholder"] = placeholder;
|
|
2080
|
+
}
|
|
2081
|
+
appendLoaderScript({
|
|
2082
|
+
attributes,
|
|
2083
|
+
onLoad,
|
|
2084
|
+
src: normalizeSaascoUrl(scriptUrl)
|
|
2085
|
+
});
|
|
2086
|
+
return "injected";
|
|
2087
|
+
}
|
|
2088
|
+
async function shouldInjectSupport({
|
|
2089
|
+
baseUrl,
|
|
2090
|
+
projectId
|
|
2091
|
+
}) {
|
|
2092
|
+
try {
|
|
2093
|
+
const response = await fetch(
|
|
2094
|
+
`${baseUrl}${SUPPORT_WIDGET_PATH}?projectId=${encodeURIComponent(projectId)}`
|
|
2095
|
+
);
|
|
2096
|
+
if (!response.ok) {
|
|
2097
|
+
return false;
|
|
2098
|
+
}
|
|
2099
|
+
return isEnabledPayload(await response.json());
|
|
2100
|
+
} catch {
|
|
2101
|
+
return false;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
function isSupportLoaderPresent() {
|
|
2105
|
+
return isLoaderPresent(SUPPORT_LOADER_FILE, window.__saascoSupportInjected);
|
|
2106
|
+
}
|
|
2107
|
+
|
|
1991
2108
|
// src/lib/analytics.ts
|
|
1992
2109
|
function getSupportGlobal() {
|
|
1993
2110
|
return window.SaascoSupport;
|
|
@@ -1997,10 +2114,6 @@ var isServer5 = !isBrowser5;
|
|
|
1997
2114
|
var PREF = "saasco-sdk";
|
|
1998
2115
|
var SESSION_DURATION = 1e3 * 60 * 30;
|
|
1999
2116
|
var USER_DURATION = 1e3 * 60 * 60 * 24 * 365;
|
|
2000
|
-
var SUPPORT_ATTR_MAP = {
|
|
2001
|
-
baseUrl: "data-base-url",
|
|
2002
|
-
placeholder: "data-placeholder"
|
|
2003
|
-
};
|
|
2004
2117
|
var data = {};
|
|
2005
2118
|
function getRootDomain(url) {
|
|
2006
2119
|
if (isServer5) {
|
|
@@ -2289,7 +2402,7 @@ var Saasco = class {
|
|
|
2289
2402
|
* @param config Configuration options.
|
|
2290
2403
|
* @param config.projectId The unique identifier for the project.
|
|
2291
2404
|
* @param config.proxy The URL of the proxy server to use, if any.
|
|
2292
|
-
* @param config.autoPageTracking Whether to automatically track page views. Default is
|
|
2405
|
+
* @param config.autoPageTracking Whether to automatically track page views. Default is true.
|
|
2293
2406
|
* @param config.enabled Whether analytics is enabled. Default is true. Set to false for development and staging envioronments. Will still allow debug mode to be true, just no events will be sent
|
|
2294
2407
|
* @param config.debug Whether to log debug information. Default is false.
|
|
2295
2408
|
* @param config.trackUrlParams Whether to track URL parameters. Default is true.
|
|
@@ -2365,52 +2478,20 @@ var Saasco = class {
|
|
|
2365
2478
|
);
|
|
2366
2479
|
}
|
|
2367
2480
|
this.initAutoPageTracking();
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
}
|
|
2371
|
-
if (this.config.socialProof?.enabled !== false) {
|
|
2372
|
-
void this.injectSocialProof();
|
|
2373
|
-
}
|
|
2481
|
+
void this.injectSupport();
|
|
2482
|
+
void this.injectSocialProof();
|
|
2374
2483
|
this.isInitialized = true;
|
|
2375
2484
|
}
|
|
2376
2485
|
disableDebug() {
|
|
2377
2486
|
this.logger.info("Debug mode deactivated.");
|
|
2378
2487
|
this.config.debug = false;
|
|
2488
|
+
this.logger.setLevel(getLoggerLevel(this.config));
|
|
2379
2489
|
}
|
|
2380
2490
|
enableDebug() {
|
|
2381
2491
|
this.config.debug = true;
|
|
2492
|
+
this.logger.setLevel(getLoggerLevel(this.config));
|
|
2382
2493
|
this.logger.info("Debug mode activated.");
|
|
2383
2494
|
}
|
|
2384
|
-
/**
|
|
2385
|
-
* Enables and injects the support widget when it was constructed with
|
|
2386
|
-
* `support: { enabled: false }`. Safe to call multiple times.
|
|
2387
|
-
*/
|
|
2388
|
-
enableSupport() {
|
|
2389
|
-
if (!this.config.support) {
|
|
2390
|
-
this.logger.warn(
|
|
2391
|
-
"Support is not configured; enableSupport() was ignored."
|
|
2392
|
-
);
|
|
2393
|
-
return;
|
|
2394
|
-
}
|
|
2395
|
-
this.config.support.enabled = true;
|
|
2396
|
-
this.injectSupport();
|
|
2397
|
-
this.pushSupportIdentity();
|
|
2398
|
-
}
|
|
2399
|
-
/**
|
|
2400
|
-
* Enables and injects the social-proof widget (e.g. after constructing with
|
|
2401
|
-
* `socialProof: { enabled: false }`, or when no `socialProof` block was
|
|
2402
|
-
* passed). Injection still runs the server check, so the loader only
|
|
2403
|
-
* downloads when the project has the app enabled in the dashboard.
|
|
2404
|
-
* Safe to call multiple times — the loader injection is guarded against
|
|
2405
|
-
* double-injection.
|
|
2406
|
-
*/
|
|
2407
|
-
enableSocialProof() {
|
|
2408
|
-
this.config.socialProof = {
|
|
2409
|
-
...this.config.socialProof,
|
|
2410
|
-
enabled: true
|
|
2411
|
-
};
|
|
2412
|
-
void this.injectSocialProof();
|
|
2413
|
-
}
|
|
2414
2495
|
/**
|
|
2415
2496
|
* Initialize third-party integrations
|
|
2416
2497
|
*/
|
|
@@ -2527,7 +2608,7 @@ var Saasco = class {
|
|
|
2527
2608
|
}
|
|
2528
2609
|
/**
|
|
2529
2610
|
* The page method lets you record page views on your website
|
|
2530
|
-
* This records the page title and path and names the event
|
|
2611
|
+
* This records the page title and path and names the event using the reserved name "Page View"
|
|
2531
2612
|
*
|
|
2532
2613
|
* Before implementing this make sure you have disabled the autoPageTracking in the config or you will get duplicate page views
|
|
2533
2614
|
*/
|
|
@@ -2751,51 +2832,25 @@ Request Data: ${JSON.stringify(requestData, null, 2)}`
|
|
|
2751
2832
|
return this.integrationManager.getStats();
|
|
2752
2833
|
}
|
|
2753
2834
|
/**
|
|
2754
|
-
* Lazily injects the support **loader**
|
|
2755
|
-
*
|
|
2756
|
-
* config as `data-*` attributes. The loader (no React) injects the
|
|
2757
|
-
* cross-origin embed iframe. Deferred (`async`) and guarded against
|
|
2758
|
-
* double-injection so re-running `init()` is a no-op.
|
|
2835
|
+
* Lazily injects the support **loader** (server-gated). See
|
|
2836
|
+
* {@link injectSupportLoader}. Replays identity once the script loads.
|
|
2759
2837
|
*/
|
|
2760
|
-
injectSupport() {
|
|
2761
|
-
if (!isBrowser5
|
|
2762
|
-
return;
|
|
2763
|
-
}
|
|
2764
|
-
const chat = this.config.support;
|
|
2765
|
-
if (!chat) {
|
|
2766
|
-
return;
|
|
2767
|
-
}
|
|
2768
|
-
if (window.__saascoSupportInjected || document.querySelector('script[src*="saasco-support-loader.js"]')) {
|
|
2769
|
-
return;
|
|
2770
|
-
}
|
|
2771
|
-
const scriptUrl = resolveLoaderScriptUrl(
|
|
2772
|
-
"saasco-support-loader.js",
|
|
2773
|
-
chat.scriptUrl
|
|
2774
|
-
);
|
|
2775
|
-
if (!scriptUrl) {
|
|
2776
|
-
this.logger.warn(
|
|
2777
|
-
"Support is enabled but the loader URL could not be resolved. Pass `support.scriptUrl` pointing at your hosted saasco-support-loader.js (or load the analytics SDK from the CDN)."
|
|
2778
|
-
);
|
|
2838
|
+
async injectSupport() {
|
|
2839
|
+
if (!isBrowser5) {
|
|
2779
2840
|
return;
|
|
2780
2841
|
}
|
|
2781
|
-
|
|
2782
|
-
const
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
script.setAttribute(
|
|
2790
|
-
attr,
|
|
2791
|
-
attr === "data-base-url" ? normalizeSaascoBaseUrl(value) : value
|
|
2792
|
-
);
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2795
|
-
script.addEventListener("load", () => {
|
|
2796
|
-
this.pushSupportIdentity();
|
|
2842
|
+
const { support } = this.config;
|
|
2843
|
+
const scriptUrl = resolveLoaderScriptUrl("saasco-support-loader.js", support?.scriptUrl) ?? `${SAASCO_ORIGIN}/sdk/saasco-support-loader.js`;
|
|
2844
|
+
const result = await injectSupportLoader({
|
|
2845
|
+
baseUrl: support?.baseUrl,
|
|
2846
|
+
onLoad: () => this.pushSupportIdentity(),
|
|
2847
|
+
placeholder: support?.placeholder,
|
|
2848
|
+
projectId: this.config.projectId,
|
|
2849
|
+
scriptUrl
|
|
2797
2850
|
});
|
|
2798
|
-
(
|
|
2851
|
+
if (result === "present") {
|
|
2852
|
+
this.pushSupportIdentity();
|
|
2853
|
+
}
|
|
2799
2854
|
}
|
|
2800
2855
|
/**
|
|
2801
2856
|
* Lazily injects the social-proof loader (server-gated). See
|
|
@@ -2818,27 +2873,23 @@ Request Data: ${JSON.stringify(requestData, null, 2)}`
|
|
|
2818
2873
|
}
|
|
2819
2874
|
/**
|
|
2820
2875
|
* Records the latest CRM identity and forwards it to the support widget.
|
|
2821
|
-
* No-op when support isn't enabled.
|
|
2822
2876
|
*/
|
|
2823
2877
|
updateSupportIdentity(identity) {
|
|
2824
|
-
if (!isBrowser5
|
|
2878
|
+
if (!isBrowser5) {
|
|
2825
2879
|
return;
|
|
2826
2880
|
}
|
|
2827
2881
|
const hasTraits = identity.traits && Object.keys(identity.traits).length > 0;
|
|
2828
2882
|
this.lastSupportIdentity = identity.distinctId || identity.email || hasTraits ? identity : null;
|
|
2829
|
-
if (this.config.support.enabled === false) {
|
|
2830
|
-
return;
|
|
2831
|
-
}
|
|
2832
2883
|
this.pushSupportIdentity();
|
|
2833
2884
|
}
|
|
2834
2885
|
/**
|
|
2835
2886
|
* Pushes the current identity onto `window.SaascoSupport.identify`. The
|
|
2836
2887
|
* widget bundle publishes that global asynchronously, so this short-polls for
|
|
2837
|
-
* it (same approach as tool registration)
|
|
2838
|
-
*
|
|
2888
|
+
* it (same approach as tool registration). `injectSupport` calls this on
|
|
2889
|
+
* script load (or immediately when the loader is already present).
|
|
2839
2890
|
*/
|
|
2840
2891
|
pushSupportIdentity() {
|
|
2841
|
-
if (!isBrowser5
|
|
2892
|
+
if (!isBrowser5) {
|
|
2842
2893
|
return;
|
|
2843
2894
|
}
|
|
2844
2895
|
const identity = this.lastSupportIdentity ?? {
|