sitepong 0.1.13 → 0.2.1
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/dist/cdn/sitepong.min.js +6 -6
- package/dist/cdn/sitepong.min.js.map +1 -1
- package/dist/entries/node.d.mts +2 -2
- package/dist/entries/node.d.ts +2 -2
- package/dist/entries/rn.js +513 -11
- package/dist/entries/rn.js.map +1 -1
- package/dist/entries/web.d.mts +2 -2
- package/dist/entries/web.d.ts +2 -2
- package/dist/entries/web.js +694 -137
- package/dist/entries/web.js.map +1 -1
- package/dist/entries/web.mjs +681 -137
- package/dist/entries/web.mjs.map +1 -1
- package/dist/index.d.mts +351 -23
- package/dist/index.d.ts +351 -23
- package/dist/index.js +367 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +354 -6
- package/dist/index.mjs.map +1 -1
- package/dist/nextjs/index.d.mts +2 -2
- package/dist/nextjs/index.d.ts +2 -2
- package/dist/react/index.d.mts +4 -4
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +367 -7
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +354 -7
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.d.mts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/{types-DQSv7JAE.d.ts → types-BTA43eyz.d.ts} +1 -1
- package/dist/{types-Cms9VXx9.d.mts → types-CphqOTfm.d.mts} +1 -1
- package/dist/{types-BEqbz0tw.d.mts → types-DPINdOQW.d.mts} +2 -0
- package/dist/{types-BEqbz0tw.d.ts → types-DPINdOQW.d.ts} +2 -0
- package/package.json +162 -160
package/dist/entries/web.mjs
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { onCLS, onINP, onLCP, onTTFB, onFCP } from 'web-vitals';
|
|
2
|
+
|
|
1
3
|
// src/platforms/web/environment.ts
|
|
2
4
|
function makeLocalStorageAdapter() {
|
|
3
5
|
try {
|
|
@@ -620,6 +622,60 @@ function clearSession() {
|
|
|
620
622
|
memorySessionTs = null;
|
|
621
623
|
}
|
|
622
624
|
|
|
625
|
+
// src/analytics/utm.ts
|
|
626
|
+
var STORAGE_KEY2 = "sp_utm";
|
|
627
|
+
var UTM_KEYS = [
|
|
628
|
+
["source", "utm_source"],
|
|
629
|
+
["medium", "utm_medium"],
|
|
630
|
+
["campaign", "utm_campaign"],
|
|
631
|
+
["term", "utm_term"],
|
|
632
|
+
["content", "utm_content"]
|
|
633
|
+
];
|
|
634
|
+
function parseFromLocation() {
|
|
635
|
+
if (typeof window === "undefined" || !window.location || !window.location.search) return null;
|
|
636
|
+
let params;
|
|
637
|
+
try {
|
|
638
|
+
params = new URLSearchParams(window.location.search);
|
|
639
|
+
} catch {
|
|
640
|
+
return null;
|
|
641
|
+
}
|
|
642
|
+
const result = {};
|
|
643
|
+
let found = false;
|
|
644
|
+
for (const [key, queryKey] of UTM_KEYS) {
|
|
645
|
+
const value = params.get(queryKey);
|
|
646
|
+
if (value) {
|
|
647
|
+
result[key] = value;
|
|
648
|
+
found = true;
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return found ? result : null;
|
|
652
|
+
}
|
|
653
|
+
function readStored() {
|
|
654
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
655
|
+
try {
|
|
656
|
+
const raw = sessionStorage.getItem(STORAGE_KEY2);
|
|
657
|
+
if (!raw) return null;
|
|
658
|
+
const parsed = JSON.parse(raw);
|
|
659
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
660
|
+
} catch {
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
function writeStored(utm) {
|
|
665
|
+
if (typeof sessionStorage === "undefined") return;
|
|
666
|
+
try {
|
|
667
|
+
sessionStorage.setItem(STORAGE_KEY2, JSON.stringify(utm));
|
|
668
|
+
} catch {
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
function getSessionUtm() {
|
|
672
|
+
const stored = readStored();
|
|
673
|
+
if (stored) return stored;
|
|
674
|
+
const fresh = parseFromLocation();
|
|
675
|
+
if (fresh) writeStored(fresh);
|
|
676
|
+
return fresh;
|
|
677
|
+
}
|
|
678
|
+
|
|
623
679
|
// src/analytics/autocapture.ts
|
|
624
680
|
var DEFAULT_BLOCK_SELECTORS = [
|
|
625
681
|
"[data-sp-no-capture]",
|
|
@@ -1026,7 +1082,9 @@ var AnalyticsManager = class {
|
|
|
1026
1082
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1027
1083
|
url: typeof window !== "undefined" && window.location ? window.location.href : void 0,
|
|
1028
1084
|
referrer: typeof document !== "undefined" && typeof document.referrer === "string" ? document.referrer : void 0,
|
|
1029
|
-
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0
|
|
1085
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
1086
|
+
utm: getSessionUtm() || void 0,
|
|
1087
|
+
appVersion: this.config.appVersion || void 0
|
|
1030
1088
|
};
|
|
1031
1089
|
}
|
|
1032
1090
|
enqueue(event) {
|
|
@@ -1724,7 +1782,7 @@ var DEFAULT_REMOTE_CONFIG = {
|
|
|
1724
1782
|
};
|
|
1725
1783
|
|
|
1726
1784
|
// src/remote-config/manager.ts
|
|
1727
|
-
var
|
|
1785
|
+
var STORAGE_KEY3 = "sitepong_remote_config";
|
|
1728
1786
|
var STORAGE_TS_KEY = "sitepong_remote_config_ts";
|
|
1729
1787
|
var RemoteConfigManager = class {
|
|
1730
1788
|
constructor(options) {
|
|
@@ -1767,7 +1825,7 @@ var RemoteConfigManager = class {
|
|
|
1767
1825
|
const storage = this.options.storage;
|
|
1768
1826
|
if (!storage) return;
|
|
1769
1827
|
try {
|
|
1770
|
-
const cached = await storage.getItem(
|
|
1828
|
+
const cached = await storage.getItem(STORAGE_KEY3);
|
|
1771
1829
|
const cachedTs = await storage.getItem(STORAGE_TS_KEY);
|
|
1772
1830
|
if (cached && cachedTs) {
|
|
1773
1831
|
const age = Date.now() - parseInt(cachedTs, 10);
|
|
@@ -1828,7 +1886,7 @@ var RemoteConfigManager = class {
|
|
|
1828
1886
|
const storage = this.options.storage;
|
|
1829
1887
|
if (!storage) return;
|
|
1830
1888
|
try {
|
|
1831
|
-
await storage.setItem(
|
|
1889
|
+
await storage.setItem(STORAGE_KEY3, JSON.stringify(this.config));
|
|
1832
1890
|
await storage.setItem(STORAGE_TS_KEY, String(Date.now()));
|
|
1833
1891
|
} catch {
|
|
1834
1892
|
this.log("Failed to cache remote config");
|
|
@@ -1862,11 +1920,70 @@ var RemoteConfigManager = class {
|
|
|
1862
1920
|
}
|
|
1863
1921
|
}
|
|
1864
1922
|
};
|
|
1865
|
-
|
|
1866
|
-
// src/performance/manager.ts
|
|
1867
1923
|
var DEFAULT_ENDPOINT3 = "https://ingest.sitepong.com";
|
|
1868
1924
|
var DEFAULT_FLUSH_INTERVAL2 = 1e4;
|
|
1869
1925
|
var MAX_FLUSH_FAILURES2 = 3;
|
|
1926
|
+
var MAX_RESOURCES_PER_FLUSH = 200;
|
|
1927
|
+
var PAGE_TIMING_POLL_INTERVAL = 200;
|
|
1928
|
+
var PAGE_TIMING_TIMEOUT = 3e4;
|
|
1929
|
+
function getPaintBlocks(resources) {
|
|
1930
|
+
const paintBlocks = [];
|
|
1931
|
+
const elements = document.getElementsByTagName("*");
|
|
1932
|
+
const styleURL = /url\(("[^"]*"|'[^']*'|[^)]*)\)/i;
|
|
1933
|
+
for (let i = 0; i < elements.length; i++) {
|
|
1934
|
+
const element = elements[i];
|
|
1935
|
+
let src = "";
|
|
1936
|
+
if (element.tagName === "IMG") {
|
|
1937
|
+
src = element.currentSrc || element.src;
|
|
1938
|
+
}
|
|
1939
|
+
if (!src) {
|
|
1940
|
+
const backgroundImage = getComputedStyle(element).getPropertyValue("background-image");
|
|
1941
|
+
if (backgroundImage) {
|
|
1942
|
+
const matches = styleURL.exec(backgroundImage);
|
|
1943
|
+
if (matches !== null) {
|
|
1944
|
+
src = matches[1];
|
|
1945
|
+
if (src.startsWith('"') || src.startsWith("'")) {
|
|
1946
|
+
src = src.substr(1, src.length - 2);
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
if (!src) continue;
|
|
1952
|
+
const time = src.substr(0, 10) === "data:image" ? 0 : resources[src];
|
|
1953
|
+
if (time === void 0) continue;
|
|
1954
|
+
const rect = element.getBoundingClientRect();
|
|
1955
|
+
const top = Math.max(rect.top, 0);
|
|
1956
|
+
const left = Math.max(rect.left, 0);
|
|
1957
|
+
const bottom = Math.min(
|
|
1958
|
+
rect.bottom,
|
|
1959
|
+
window.innerHeight || document.documentElement && document.documentElement.clientHeight || 0
|
|
1960
|
+
);
|
|
1961
|
+
const right = Math.min(
|
|
1962
|
+
rect.right,
|
|
1963
|
+
window.innerWidth || document.documentElement && document.documentElement.clientWidth || 0
|
|
1964
|
+
);
|
|
1965
|
+
if (bottom <= top || right <= left) continue;
|
|
1966
|
+
const area = (bottom - top) * (right - left);
|
|
1967
|
+
paintBlocks.push({ time, area });
|
|
1968
|
+
}
|
|
1969
|
+
return paintBlocks;
|
|
1970
|
+
}
|
|
1971
|
+
function calculateSpeedIndex(firstContentfulPaint, paintBlocks) {
|
|
1972
|
+
let a = Math.max(
|
|
1973
|
+
document.documentElement && document.documentElement.clientWidth || 0,
|
|
1974
|
+
window.innerWidth || 0
|
|
1975
|
+
) * Math.max(
|
|
1976
|
+
document.documentElement && document.documentElement.clientHeight || 0,
|
|
1977
|
+
window.innerHeight || 0
|
|
1978
|
+
) / 10;
|
|
1979
|
+
let s = a * firstContentfulPaint;
|
|
1980
|
+
for (let i = 0; i < paintBlocks.length; i++) {
|
|
1981
|
+
const { time, area } = paintBlocks[i];
|
|
1982
|
+
a += area;
|
|
1983
|
+
s += area * (time > firstContentfulPaint ? time : firstContentfulPaint);
|
|
1984
|
+
}
|
|
1985
|
+
return a === 0 ? 0 : s / a;
|
|
1986
|
+
}
|
|
1870
1987
|
var PerformanceManager = class {
|
|
1871
1988
|
constructor(config) {
|
|
1872
1989
|
this.metrics = [];
|
|
@@ -1875,12 +1992,22 @@ var PerformanceManager = class {
|
|
|
1875
1992
|
this.disabled = false;
|
|
1876
1993
|
this.vitals = {};
|
|
1877
1994
|
this.activeTransactions = /* @__PURE__ */ new Map();
|
|
1995
|
+
// Resource timing state for Speed Index
|
|
1996
|
+
this.resourceObserver = null;
|
|
1997
|
+
this.resourceTimeMap = {};
|
|
1998
|
+
this.resourceCount = 0;
|
|
1999
|
+
// Page timing polling timers
|
|
2000
|
+
this.pageLoadTimer = null;
|
|
2001
|
+
this.pageRenderTimer = null;
|
|
1878
2002
|
this.config = {
|
|
1879
2003
|
endpoint: DEFAULT_ENDPOINT3,
|
|
1880
2004
|
enabled: true,
|
|
1881
2005
|
webVitals: true,
|
|
1882
2006
|
navigationTiming: true,
|
|
1883
|
-
resourceTiming:
|
|
2007
|
+
resourceTiming: true,
|
|
2008
|
+
capturePageLoadTimings: true,
|
|
2009
|
+
capturePageRenderTimings: true,
|
|
2010
|
+
excludedResourceUrls: [],
|
|
1884
2011
|
flushInterval: DEFAULT_FLUSH_INTERVAL2,
|
|
1885
2012
|
sampleRate: 1,
|
|
1886
2013
|
debug: false,
|
|
@@ -1891,18 +2018,250 @@ var PerformanceManager = class {
|
|
|
1891
2018
|
init() {
|
|
1892
2019
|
if (!this.config.enabled || !this.sampled) return;
|
|
1893
2020
|
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return;
|
|
1894
|
-
if (this.config.webVitals) {
|
|
1895
|
-
this.
|
|
2021
|
+
if (this.config.webVitals !== false) {
|
|
2022
|
+
this.initWebVitals();
|
|
2023
|
+
}
|
|
2024
|
+
if (this.config.resourceTiming !== false) {
|
|
2025
|
+
this.initResourceTiming();
|
|
2026
|
+
}
|
|
2027
|
+
if (this.config.capturePageLoadTimings !== false) {
|
|
2028
|
+
this.initPageLoadTiming();
|
|
1896
2029
|
}
|
|
1897
|
-
if (this.config.
|
|
1898
|
-
this.
|
|
2030
|
+
if (this.config.capturePageRenderTimings !== false) {
|
|
2031
|
+
this.initPageRenderTiming();
|
|
1899
2032
|
}
|
|
1900
2033
|
this.startFlushTimer();
|
|
1901
2034
|
this.log("Performance monitoring initialized");
|
|
1902
2035
|
}
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2036
|
+
// ---- Web Vitals (via web-vitals library) ----
|
|
2037
|
+
initWebVitals() {
|
|
2038
|
+
onCLS((m) => {
|
|
2039
|
+
this.vitals.cls = m.value;
|
|
2040
|
+
this.reportVital("CLS", m.value, "score");
|
|
2041
|
+
});
|
|
2042
|
+
onINP((m) => {
|
|
2043
|
+
this.vitals.inp = m.value;
|
|
2044
|
+
this.reportVital("INP", m.value);
|
|
2045
|
+
});
|
|
2046
|
+
onLCP((m) => {
|
|
2047
|
+
this.vitals.lcp = m.value;
|
|
2048
|
+
this.reportVital("LCP", m.value);
|
|
2049
|
+
});
|
|
2050
|
+
onTTFB((m) => {
|
|
2051
|
+
this.vitals.ttfb = m.value;
|
|
2052
|
+
this.reportVital("TTFB", m.value);
|
|
2053
|
+
});
|
|
2054
|
+
onFCP((m) => {
|
|
2055
|
+
this.vitals.fcp = m.value;
|
|
2056
|
+
this.reportVital("FCP", m.value);
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
// ---- Resource Timing (adapted from OpenReplay timing.ts) ----
|
|
2060
|
+
initResourceTiming() {
|
|
2061
|
+
if (typeof PerformanceObserver === "undefined") return;
|
|
2062
|
+
try {
|
|
2063
|
+
this.resourceObserver = new PerformanceObserver((list) => {
|
|
2064
|
+
for (const entry of list.getEntries()) {
|
|
2065
|
+
this.processResourceEntry(entry);
|
|
2066
|
+
}
|
|
2067
|
+
});
|
|
2068
|
+
this.resourceObserver.observe({ type: "resource", buffered: true });
|
|
2069
|
+
} catch {
|
|
2070
|
+
this.log("PerformanceObserver for resource timing not supported");
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
isServiceURL(url) {
|
|
2074
|
+
const endpoint = this.config.performanceEndpoint || this.config.endpoint;
|
|
2075
|
+
return url.startsWith(endpoint);
|
|
2076
|
+
}
|
|
2077
|
+
processResourceEntry(entry) {
|
|
2078
|
+
if (entry.duration < 0 || !entry.name.startsWith("http")) return;
|
|
2079
|
+
if (this.isServiceURL(entry.name)) return;
|
|
2080
|
+
if (this.resourceTimeMap !== null) {
|
|
2081
|
+
this.resourceTimeMap[entry.name] = entry.startTime + entry.duration;
|
|
2082
|
+
}
|
|
2083
|
+
for (const excluded of this.config.excludedResourceUrls) {
|
|
2084
|
+
if (entry.name.startsWith(excluded)) return;
|
|
2085
|
+
}
|
|
2086
|
+
if (this.resourceCount >= MAX_RESOURCES_PER_FLUSH) return;
|
|
2087
|
+
this.resourceCount++;
|
|
2088
|
+
let stalled = 0;
|
|
2089
|
+
if (entry.connectEnd && entry.connectEnd > entry.domainLookupEnd) {
|
|
2090
|
+
stalled = Math.max(0, entry.requestStart - entry.connectEnd);
|
|
2091
|
+
} else {
|
|
2092
|
+
stalled = Math.max(0, entry.requestStart - entry.domainLookupEnd);
|
|
2093
|
+
}
|
|
2094
|
+
const cached = entry.responseStatus && entry.responseStatus === 304 || entry.deliveryType && entry.deliveryType === "cache" || entry.transferSize === 0 && entry.decodedBodySize > 0;
|
|
2095
|
+
const responseStatus = entry.responseStatus || 0;
|
|
2096
|
+
const failed = responseStatus >= 400;
|
|
2097
|
+
const breakdown = {
|
|
2098
|
+
queueing: entry.requestStart - entry.fetchStart,
|
|
2099
|
+
dnsLookup: entry.domainLookupEnd - entry.domainLookupStart,
|
|
2100
|
+
initialConnection: entry.connectEnd - entry.connectStart,
|
|
2101
|
+
ssl: entry.secureConnectionStart > 0 ? entry.connectEnd - entry.secureConnectionStart : 0,
|
|
2102
|
+
ttfb: entry.responseStart - entry.requestStart,
|
|
2103
|
+
contentDownload: entry.responseEnd - entry.responseStart,
|
|
2104
|
+
total: entry.duration ?? entry.responseEnd - entry.startTime,
|
|
2105
|
+
stalled,
|
|
2106
|
+
cached,
|
|
2107
|
+
failed,
|
|
2108
|
+
responseStatus,
|
|
2109
|
+
headerSize: entry.transferSize > entry.encodedBodySize ? entry.transferSize - entry.encodedBodySize : 0,
|
|
2110
|
+
encodedBodySize: entry.encodedBodySize || 0,
|
|
2111
|
+
decodedBodySize: failed ? -111 : entry.decodedBodySize || 0,
|
|
2112
|
+
transferSize: entry.transferSize,
|
|
2113
|
+
initiatorType: entry.initiatorType
|
|
2114
|
+
};
|
|
2115
|
+
const entryName = this.config.resourceNameSanitizer ? this.config.resourceNameSanitizer(entry.name) : entry.name;
|
|
2116
|
+
this.addMetric({
|
|
2117
|
+
type: "resource",
|
|
2118
|
+
name: entryName,
|
|
2119
|
+
value: entry.duration,
|
|
2120
|
+
unit: "ms",
|
|
2121
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2122
|
+
url: typeof window !== "undefined" && window.location ? window.location.href : void 0,
|
|
2123
|
+
data: breakdown
|
|
2124
|
+
});
|
|
2125
|
+
}
|
|
2126
|
+
// ---- Page Load Timing (adapted from OpenReplay timing.ts) ----
|
|
2127
|
+
initPageLoadTiming() {
|
|
2128
|
+
if (typeof window === "undefined" || !window.performance) return;
|
|
2129
|
+
let firstPaint = 0;
|
|
2130
|
+
let firstContentfulPaint = 0;
|
|
2131
|
+
let sent = false;
|
|
2132
|
+
const startTime = performance.now();
|
|
2133
|
+
this.pageLoadTimer = setInterval(() => {
|
|
2134
|
+
if (sent) {
|
|
2135
|
+
if (this.pageLoadTimer) clearInterval(this.pageLoadTimer);
|
|
2136
|
+
return;
|
|
2137
|
+
}
|
|
2138
|
+
if (firstPaint === 0 || firstContentfulPaint === 0) {
|
|
2139
|
+
for (const entry of performance.getEntriesByType("paint")) {
|
|
2140
|
+
if (entry.name === "first-paint") firstPaint = entry.startTime;
|
|
2141
|
+
if (entry.name === "first-contentful-paint") firstContentfulPaint = entry.startTime;
|
|
2142
|
+
}
|
|
2143
|
+
}
|
|
2144
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
2145
|
+
const timedOut = performance.now() - startTime > PAGE_TIMING_TIMEOUT;
|
|
2146
|
+
if (nav && nav.loadEventEnd > 0 || timedOut) {
|
|
2147
|
+
sent = true;
|
|
2148
|
+
if (this.pageLoadTimer) clearInterval(this.pageLoadTimer);
|
|
2149
|
+
if (nav) {
|
|
2150
|
+
const navigationStart = nav.startTime;
|
|
2151
|
+
this.addMetric({
|
|
2152
|
+
type: "navigation",
|
|
2153
|
+
name: "page_load",
|
|
2154
|
+
value: nav.loadEventEnd - navigationStart,
|
|
2155
|
+
unit: "ms",
|
|
2156
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2157
|
+
url: window.location.href,
|
|
2158
|
+
data: {
|
|
2159
|
+
requestStart: nav.requestStart - navigationStart,
|
|
2160
|
+
responseStart: nav.responseStart - navigationStart,
|
|
2161
|
+
responseEnd: nav.responseEnd - navigationStart,
|
|
2162
|
+
domContentLoadedEventStart: nav.domContentLoadedEventEnd - navigationStart,
|
|
2163
|
+
domContentLoadedEventEnd: nav.domContentLoadedEventEnd - navigationStart,
|
|
2164
|
+
loadEventStart: nav.loadEventStart - navigationStart,
|
|
2165
|
+
loadEventEnd: nav.loadEventEnd - navigationStart,
|
|
2166
|
+
firstPaint,
|
|
2167
|
+
firstContentfulPaint,
|
|
2168
|
+
dns: nav.domainLookupEnd - nav.domainLookupStart,
|
|
2169
|
+
tcp: nav.connectEnd - nav.connectStart,
|
|
2170
|
+
ttfb: nav.responseStart - nav.requestStart,
|
|
2171
|
+
domComplete: nav.domComplete - navigationStart,
|
|
2172
|
+
transferSize: nav.transferSize,
|
|
2173
|
+
encodedBodySize: nav.encodedBodySize,
|
|
2174
|
+
decodedBodySize: nav.decodedBodySize
|
|
2175
|
+
}
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
}, PAGE_TIMING_POLL_INTERVAL);
|
|
2180
|
+
}
|
|
2181
|
+
// ---- Page Render Timing: Speed Index, Visually Complete, TTI (adapted from OpenReplay) ----
|
|
2182
|
+
initPageRenderTiming() {
|
|
2183
|
+
if (typeof window === "undefined" || !window.performance) return;
|
|
2184
|
+
let firstContentfulPaint = 0;
|
|
2185
|
+
let visuallyComplete = 0;
|
|
2186
|
+
let interactiveWindowStartTime = 0;
|
|
2187
|
+
let interactiveWindowTickTime = 0;
|
|
2188
|
+
let paintBlocks = null;
|
|
2189
|
+
let sent = false;
|
|
2190
|
+
const startTime = performance.now();
|
|
2191
|
+
this.pageRenderTimer = setInterval(() => {
|
|
2192
|
+
if (sent) {
|
|
2193
|
+
if (this.pageRenderTimer) clearInterval(this.pageRenderTimer);
|
|
2194
|
+
return;
|
|
2195
|
+
}
|
|
2196
|
+
const time = performance.now();
|
|
2197
|
+
if (firstContentfulPaint === 0) {
|
|
2198
|
+
for (const entry of performance.getEntriesByType("paint")) {
|
|
2199
|
+
if (entry.name === "first-contentful-paint") {
|
|
2200
|
+
firstContentfulPaint = entry.startTime;
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
if (this.resourceTimeMap !== null) {
|
|
2205
|
+
const times = Object.values(this.resourceTimeMap);
|
|
2206
|
+
if (times.length > 0) {
|
|
2207
|
+
visuallyComplete = Math.max(...times);
|
|
2208
|
+
}
|
|
2209
|
+
if (time - visuallyComplete > 1e3) {
|
|
2210
|
+
paintBlocks = getPaintBlocks(this.resourceTimeMap);
|
|
2211
|
+
this.resourceTimeMap = null;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
if (interactiveWindowTickTime !== null) {
|
|
2215
|
+
if (time - interactiveWindowTickTime > 50) {
|
|
2216
|
+
interactiveWindowStartTime = time;
|
|
2217
|
+
}
|
|
2218
|
+
interactiveWindowTickTime = time - interactiveWindowStartTime > 5e3 ? null : time;
|
|
2219
|
+
}
|
|
2220
|
+
const timedOut = time - startTime > PAGE_TIMING_TIMEOUT;
|
|
2221
|
+
if (paintBlocks !== null && interactiveWindowTickTime === null || timedOut) {
|
|
2222
|
+
sent = true;
|
|
2223
|
+
if (this.pageRenderTimer) clearInterval(this.pageRenderTimer);
|
|
2224
|
+
this.resourceTimeMap = null;
|
|
2225
|
+
const speedIndex = paintBlocks === null ? 0 : calculateSpeedIndex(firstContentfulPaint || 0, paintBlocks);
|
|
2226
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
2227
|
+
const domContentLoadedEnd = nav ? nav.domContentLoadedEventEnd - nav.startTime : 0;
|
|
2228
|
+
const timeToInteractive = interactiveWindowTickTime === null ? Math.max(interactiveWindowStartTime, firstContentfulPaint, domContentLoadedEnd) : 0;
|
|
2229
|
+
const url = window.location.href;
|
|
2230
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2231
|
+
if (speedIndex > 0) {
|
|
2232
|
+
this.addMetric({
|
|
2233
|
+
type: "page_render",
|
|
2234
|
+
name: "speed_index",
|
|
2235
|
+
value: Math.round(speedIndex),
|
|
2236
|
+
unit: "ms",
|
|
2237
|
+
timestamp,
|
|
2238
|
+
url
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
if (visuallyComplete > 0) {
|
|
2242
|
+
this.addMetric({
|
|
2243
|
+
type: "page_render",
|
|
2244
|
+
name: "visually_complete",
|
|
2245
|
+
value: Math.round(visuallyComplete),
|
|
2246
|
+
unit: "ms",
|
|
2247
|
+
timestamp,
|
|
2248
|
+
url
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
if (timeToInteractive > 0) {
|
|
2252
|
+
this.addMetric({
|
|
2253
|
+
type: "page_render",
|
|
2254
|
+
name: "tti",
|
|
2255
|
+
value: Math.round(timeToInteractive),
|
|
2256
|
+
unit: "ms",
|
|
2257
|
+
timestamp,
|
|
2258
|
+
url
|
|
2259
|
+
});
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
}, PAGE_TIMING_POLL_INTERVAL);
|
|
2263
|
+
}
|
|
2264
|
+
// ---- Transactions / Spans (unchanged) ----
|
|
1906
2265
|
startTransaction(name, data) {
|
|
1907
2266
|
const id = `txn_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 6)}`;
|
|
1908
2267
|
const transaction = {
|
|
@@ -1917,9 +2276,6 @@ var PerformanceManager = class {
|
|
|
1917
2276
|
this.log("Transaction started:", name, id);
|
|
1918
2277
|
return id;
|
|
1919
2278
|
}
|
|
1920
|
-
/**
|
|
1921
|
-
* End a transaction and report it
|
|
1922
|
-
*/
|
|
1923
2279
|
endTransaction(id, status = "ok") {
|
|
1924
2280
|
const transaction = this.activeTransactions.get(id);
|
|
1925
2281
|
if (!transaction) {
|
|
@@ -1948,9 +2304,6 @@ var PerformanceManager = class {
|
|
|
1948
2304
|
});
|
|
1949
2305
|
this.log("Transaction ended:", transaction.name, `${transaction.duration.toFixed(1)}ms`);
|
|
1950
2306
|
}
|
|
1951
|
-
/**
|
|
1952
|
-
* Start a span within a transaction
|
|
1953
|
-
*/
|
|
1954
2307
|
startSpan(transactionId, name, data) {
|
|
1955
2308
|
const transaction = this.activeTransactions.get(transactionId);
|
|
1956
2309
|
if (!transaction) {
|
|
@@ -1967,9 +2320,6 @@ var PerformanceManager = class {
|
|
|
1967
2320
|
transaction.spans.push(span);
|
|
1968
2321
|
return span.id;
|
|
1969
2322
|
}
|
|
1970
|
-
/**
|
|
1971
|
-
* End a span
|
|
1972
|
-
*/
|
|
1973
2323
|
endSpan(transactionId, spanId, status = "ok") {
|
|
1974
2324
|
const transaction = this.activeTransactions.get(transactionId);
|
|
1975
2325
|
if (!transaction) return;
|
|
@@ -1979,9 +2329,7 @@ var PerformanceManager = class {
|
|
|
1979
2329
|
span.duration = span.endTime - span.startTime;
|
|
1980
2330
|
span.status = status;
|
|
1981
2331
|
}
|
|
1982
|
-
|
|
1983
|
-
* Get current Web Vitals
|
|
1984
|
-
*/
|
|
2332
|
+
// ---- Public API ----
|
|
1985
2333
|
getVitals() {
|
|
1986
2334
|
return { ...this.vitals };
|
|
1987
2335
|
}
|
|
@@ -1990,116 +2338,21 @@ var PerformanceManager = class {
|
|
|
1990
2338
|
clearInterval(this.flushTimer);
|
|
1991
2339
|
this.flushTimer = null;
|
|
1992
2340
|
}
|
|
1993
|
-
this.
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
if (typeof PerformanceObserver === "undefined") return;
|
|
1997
|
-
try {
|
|
1998
|
-
const lcpObserver = new PerformanceObserver((list) => {
|
|
1999
|
-
const entries = list.getEntries();
|
|
2000
|
-
const lastEntry = entries[entries.length - 1];
|
|
2001
|
-
if (lastEntry) {
|
|
2002
|
-
this.vitals.lcp = lastEntry.startTime;
|
|
2003
|
-
this.reportVital("LCP", lastEntry.startTime);
|
|
2004
|
-
}
|
|
2005
|
-
});
|
|
2006
|
-
lcpObserver.observe({ type: "largest-contentful-paint", buffered: true });
|
|
2007
|
-
} catch (e) {
|
|
2008
|
-
}
|
|
2009
|
-
try {
|
|
2010
|
-
const fidObserver = new PerformanceObserver((list) => {
|
|
2011
|
-
const entry = list.getEntries()[0];
|
|
2012
|
-
if (entry) {
|
|
2013
|
-
const fid = entry.processingStart - entry.startTime;
|
|
2014
|
-
this.vitals.fid = fid;
|
|
2015
|
-
this.reportVital("FID", fid);
|
|
2016
|
-
}
|
|
2017
|
-
});
|
|
2018
|
-
fidObserver.observe({ type: "first-input", buffered: true });
|
|
2019
|
-
} catch (e) {
|
|
2020
|
-
}
|
|
2021
|
-
try {
|
|
2022
|
-
let clsValue = 0;
|
|
2023
|
-
const clsObserver = new PerformanceObserver((list) => {
|
|
2024
|
-
for (const entry of list.getEntries()) {
|
|
2025
|
-
const layoutShift = entry;
|
|
2026
|
-
if (!layoutShift.hadRecentInput) {
|
|
2027
|
-
clsValue += layoutShift.value;
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
this.vitals.cls = clsValue;
|
|
2031
|
-
});
|
|
2032
|
-
clsObserver.observe({ type: "layout-shift", buffered: true });
|
|
2033
|
-
if (typeof document !== "undefined") {
|
|
2034
|
-
document.addEventListener("visibilitychange", () => {
|
|
2035
|
-
if (document.visibilityState === "hidden" && clsValue > 0) {
|
|
2036
|
-
this.reportVital("CLS", clsValue, "score");
|
|
2037
|
-
}
|
|
2038
|
-
});
|
|
2039
|
-
}
|
|
2040
|
-
} catch (e) {
|
|
2041
|
-
}
|
|
2042
|
-
try {
|
|
2043
|
-
const fcpObserver = new PerformanceObserver((list) => {
|
|
2044
|
-
const entry = list.getEntries().find(
|
|
2045
|
-
(e) => e.name === "first-contentful-paint"
|
|
2046
|
-
);
|
|
2047
|
-
if (entry) {
|
|
2048
|
-
this.vitals.fcp = entry.startTime;
|
|
2049
|
-
this.reportVital("FCP", entry.startTime);
|
|
2050
|
-
}
|
|
2051
|
-
});
|
|
2052
|
-
fcpObserver.observe({ type: "paint", buffered: true });
|
|
2053
|
-
} catch (e) {
|
|
2341
|
+
if (this.pageLoadTimer) {
|
|
2342
|
+
clearInterval(this.pageLoadTimer);
|
|
2343
|
+
this.pageLoadTimer = null;
|
|
2054
2344
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
for (const entry of list.getEntries()) {
|
|
2059
|
-
const duration = entry.duration;
|
|
2060
|
-
if (duration > maxINP) {
|
|
2061
|
-
maxINP = duration;
|
|
2062
|
-
this.vitals.inp = maxINP;
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
});
|
|
2066
|
-
inpObserver.observe({ type: "event", buffered: true });
|
|
2067
|
-
} catch (e) {
|
|
2345
|
+
if (this.pageRenderTimer) {
|
|
2346
|
+
clearInterval(this.pageRenderTimer);
|
|
2347
|
+
this.pageRenderTimer = null;
|
|
2068
2348
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
const collect = () => {
|
|
2073
|
-
const nav = performance.getEntriesByType("navigation")[0];
|
|
2074
|
-
if (!nav) return;
|
|
2075
|
-
const ttfb = nav.responseStart - nav.requestStart;
|
|
2076
|
-
this.vitals.ttfb = ttfb;
|
|
2077
|
-
this.reportVital("TTFB", ttfb);
|
|
2078
|
-
this.addMetric({
|
|
2079
|
-
type: "navigation",
|
|
2080
|
-
name: "page_load",
|
|
2081
|
-
value: nav.loadEventEnd - nav.startTime,
|
|
2082
|
-
unit: "ms",
|
|
2083
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2084
|
-
url: window.location.href,
|
|
2085
|
-
data: {
|
|
2086
|
-
dns: nav.domainLookupEnd - nav.domainLookupStart,
|
|
2087
|
-
tcp: nav.connectEnd - nav.connectStart,
|
|
2088
|
-
ttfb,
|
|
2089
|
-
domContentLoaded: nav.domContentLoadedEventEnd - nav.startTime,
|
|
2090
|
-
domComplete: nav.domComplete - nav.startTime,
|
|
2091
|
-
transferSize: nav.transferSize,
|
|
2092
|
-
encodedBodySize: nav.encodedBodySize,
|
|
2093
|
-
decodedBodySize: nav.decodedBodySize
|
|
2094
|
-
}
|
|
2095
|
-
});
|
|
2096
|
-
};
|
|
2097
|
-
if (document.readyState === "complete") {
|
|
2098
|
-
setTimeout(collect, 0);
|
|
2099
|
-
} else {
|
|
2100
|
-
window.addEventListener("load", () => setTimeout(collect, 0));
|
|
2349
|
+
if (this.resourceObserver) {
|
|
2350
|
+
this.resourceObserver.disconnect();
|
|
2351
|
+
this.resourceObserver = null;
|
|
2101
2352
|
}
|
|
2353
|
+
this.flush();
|
|
2102
2354
|
}
|
|
2355
|
+
// ---- Internal ----
|
|
2103
2356
|
reportVital(name, value, unit = "ms") {
|
|
2104
2357
|
this.addMetric({
|
|
2105
2358
|
type: "web_vital",
|
|
@@ -2133,6 +2386,7 @@ var PerformanceManager = class {
|
|
|
2133
2386
|
}
|
|
2134
2387
|
const metrics = [...this.metrics];
|
|
2135
2388
|
this.metrics = [];
|
|
2389
|
+
this.resourceCount = 0;
|
|
2136
2390
|
const endpoint = this.config.performanceEndpoint || `${this.config.endpoint}/api/performance`;
|
|
2137
2391
|
try {
|
|
2138
2392
|
const response = await fetch(endpoint, {
|
|
@@ -2310,6 +2564,292 @@ var TracePropagator = class {
|
|
|
2310
2564
|
}
|
|
2311
2565
|
};
|
|
2312
2566
|
|
|
2567
|
+
// src/superlink/client.ts
|
|
2568
|
+
var DEFAULT_SUPERLINK_ENDPOINT = "https://pongl.ink";
|
|
2569
|
+
var SuperLinkClient = class {
|
|
2570
|
+
constructor(config = {}) {
|
|
2571
|
+
this.config = {
|
|
2572
|
+
endpoint: stripTrailingSlash(config.endpoint || DEFAULT_SUPERLINK_ENDPOINT),
|
|
2573
|
+
appId: config.appId,
|
|
2574
|
+
installId: config.installId,
|
|
2575
|
+
debug: config.debug ?? false
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
/** Replace config in place (used by init() so module-level helpers see updates). */
|
|
2579
|
+
configure(config) {
|
|
2580
|
+
if (config.endpoint) this.config.endpoint = stripTrailingSlash(config.endpoint);
|
|
2581
|
+
if (config.appId !== void 0) this.config.appId = config.appId;
|
|
2582
|
+
if (config.installId !== void 0) this.config.installId = config.installId;
|
|
2583
|
+
if (config.debug !== void 0) this.config.debug = config.debug;
|
|
2584
|
+
}
|
|
2585
|
+
log(...args) {
|
|
2586
|
+
if (this.config.debug) console.warn("[SuperLink]", ...args);
|
|
2587
|
+
}
|
|
2588
|
+
/**
|
|
2589
|
+
* POST /match — ask the redirect engine to resolve a deferred deep link from
|
|
2590
|
+
* a click token (Android referrer / iOS clipboard) and/or a device
|
|
2591
|
+
* fingerprint. Returns `{ matched: false }` on any error.
|
|
2592
|
+
*/
|
|
2593
|
+
async match(body) {
|
|
2594
|
+
const payload = {
|
|
2595
|
+
...body,
|
|
2596
|
+
install_id: body.install_id ?? this.config.installId
|
|
2597
|
+
};
|
|
2598
|
+
try {
|
|
2599
|
+
const res = await fetch(`${this.config.endpoint}/match`, {
|
|
2600
|
+
method: "POST",
|
|
2601
|
+
headers: { "Content-Type": "application/json" },
|
|
2602
|
+
body: JSON.stringify(payload)
|
|
2603
|
+
});
|
|
2604
|
+
if (!res.ok) {
|
|
2605
|
+
this.log("match failed", res.status);
|
|
2606
|
+
return { matched: false };
|
|
2607
|
+
}
|
|
2608
|
+
const data = await res.json();
|
|
2609
|
+
return data ?? { matched: false };
|
|
2610
|
+
} catch (err) {
|
|
2611
|
+
this.log("match error", err);
|
|
2612
|
+
return { matched: false };
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
/**
|
|
2616
|
+
* POST /events — report a lifecycle event (opened / converted) back to the
|
|
2617
|
+
* redirect engine, which fans out to analytics + webhooks. Best-effort.
|
|
2618
|
+
*/
|
|
2619
|
+
async reportEvent(input) {
|
|
2620
|
+
try {
|
|
2621
|
+
const res = await fetch(`${this.config.endpoint}/events`, {
|
|
2622
|
+
method: "POST",
|
|
2623
|
+
headers: { "Content-Type": "application/json" },
|
|
2624
|
+
body: JSON.stringify({
|
|
2625
|
+
app_id: this.config.appId,
|
|
2626
|
+
install_id: this.config.installId,
|
|
2627
|
+
...input
|
|
2628
|
+
})
|
|
2629
|
+
});
|
|
2630
|
+
if (!res.ok) this.log("event failed", input.type, res.status);
|
|
2631
|
+
return res.ok;
|
|
2632
|
+
} catch (err) {
|
|
2633
|
+
this.log("event error", err);
|
|
2634
|
+
return false;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
};
|
|
2638
|
+
function stripTrailingSlash(url) {
|
|
2639
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
2640
|
+
}
|
|
2641
|
+
var superlinkClient = new SuperLinkClient();
|
|
2642
|
+
|
|
2643
|
+
// src/superlink/parse.ts
|
|
2644
|
+
var UTM_KEYS2 = [
|
|
2645
|
+
["source", "utm_source"],
|
|
2646
|
+
["medium", "utm_medium"],
|
|
2647
|
+
["campaign", "utm_campaign"],
|
|
2648
|
+
["term", "utm_term"],
|
|
2649
|
+
["content", "utm_content"]
|
|
2650
|
+
];
|
|
2651
|
+
function parseUniversalLink(url) {
|
|
2652
|
+
let parsed;
|
|
2653
|
+
try {
|
|
2654
|
+
parsed = new URL(url);
|
|
2655
|
+
} catch {
|
|
2656
|
+
return null;
|
|
2657
|
+
}
|
|
2658
|
+
const params = parsed.searchParams;
|
|
2659
|
+
const utm = {};
|
|
2660
|
+
for (const [key, queryKey] of UTM_KEYS2) {
|
|
2661
|
+
const value = params.get(queryKey);
|
|
2662
|
+
if (value) utm[key] = value;
|
|
2663
|
+
}
|
|
2664
|
+
const referral = {};
|
|
2665
|
+
const deep_link_data = {};
|
|
2666
|
+
params.forEach((value, key) => {
|
|
2667
|
+
if (key.startsWith("r_")) {
|
|
2668
|
+
referral[key.slice(2)] = value;
|
|
2669
|
+
} else if (key.startsWith("~")) {
|
|
2670
|
+
deep_link_data[key.slice(1)] = value;
|
|
2671
|
+
}
|
|
2672
|
+
});
|
|
2673
|
+
const explicitPath = params.get("$deep_link_path") ?? params.get("dlp");
|
|
2674
|
+
const deep_link_path = explicitPath ?? (parsed.pathname && parsed.pathname !== "/" ? parsed.pathname : null);
|
|
2675
|
+
return {
|
|
2676
|
+
deep_link_path,
|
|
2677
|
+
deep_link_data,
|
|
2678
|
+
utm,
|
|
2679
|
+
referral,
|
|
2680
|
+
click_id: params.get("click_id"),
|
|
2681
|
+
match_type: "none",
|
|
2682
|
+
confidence: 1
|
|
2683
|
+
};
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
// src/superlink/deferred.ts
|
|
2687
|
+
var handlers = /* @__PURE__ */ new Set();
|
|
2688
|
+
var lastMatched = null;
|
|
2689
|
+
function toDeepLink(res) {
|
|
2690
|
+
return {
|
|
2691
|
+
deep_link_path: res.deep_link_path ?? null,
|
|
2692
|
+
deep_link_data: res.deep_link_data ?? {},
|
|
2693
|
+
utm: res.utm ?? {},
|
|
2694
|
+
referral: res.referral ?? {},
|
|
2695
|
+
click_id: res.click_id ?? null,
|
|
2696
|
+
match_type: res.match_type ?? "fingerprint",
|
|
2697
|
+
confidence: res.confidence ?? (res.match_type && res.match_type !== "none" ? 1 : 0)
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
function emitDeferredDeepLink(link) {
|
|
2701
|
+
lastMatched = link;
|
|
2702
|
+
for (const handler of handlers) {
|
|
2703
|
+
try {
|
|
2704
|
+
handler(link);
|
|
2705
|
+
} catch (err) {
|
|
2706
|
+
if (superlinkClient.config.debug) console.warn("[SuperLink] handler threw", err);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
function onDeferredDeepLink(handler) {
|
|
2711
|
+
handlers.add(handler);
|
|
2712
|
+
if (lastMatched) {
|
|
2713
|
+
try {
|
|
2714
|
+
handler(lastMatched);
|
|
2715
|
+
} catch {
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
return () => {
|
|
2719
|
+
handlers.delete(handler);
|
|
2720
|
+
};
|
|
2721
|
+
}
|
|
2722
|
+
function getMatchedDeepLink() {
|
|
2723
|
+
return lastMatched;
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
// src/superlink/web.ts
|
|
2727
|
+
var STORAGE_KEY4 = "sp_superlink";
|
|
2728
|
+
var captured = null;
|
|
2729
|
+
var didCapture = false;
|
|
2730
|
+
function readStored2() {
|
|
2731
|
+
if (typeof sessionStorage === "undefined") return null;
|
|
2732
|
+
try {
|
|
2733
|
+
const raw = sessionStorage.getItem(STORAGE_KEY4);
|
|
2734
|
+
if (!raw) return null;
|
|
2735
|
+
const parsed = JSON.parse(raw);
|
|
2736
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
2737
|
+
} catch {
|
|
2738
|
+
return null;
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
function writeStored2(link) {
|
|
2742
|
+
if (typeof sessionStorage === "undefined") return;
|
|
2743
|
+
try {
|
|
2744
|
+
sessionStorage.setItem(STORAGE_KEY4, JSON.stringify(link));
|
|
2745
|
+
} catch {
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
function hasPayload(link) {
|
|
2749
|
+
return Boolean(
|
|
2750
|
+
link.deep_link_path || link.click_id || Object.keys(link.deep_link_data).length > 0 || Object.keys(link.referral).length > 0 || Object.keys(link.utm).length > 0
|
|
2751
|
+
);
|
|
2752
|
+
}
|
|
2753
|
+
function writeClipboardToken(clickId) {
|
|
2754
|
+
if (typeof navigator === "undefined" || !navigator.clipboard) return;
|
|
2755
|
+
const url = `${superlinkClient.config.endpoint}/c/${clickId}`;
|
|
2756
|
+
navigator.clipboard.writeText(url).catch(() => {
|
|
2757
|
+
});
|
|
2758
|
+
}
|
|
2759
|
+
function extractIdentityMetadata(url) {
|
|
2760
|
+
const href = url ?? (typeof window !== "undefined" && window.location ? window.location.href : null);
|
|
2761
|
+
if (!href) return void 0;
|
|
2762
|
+
let loc;
|
|
2763
|
+
try {
|
|
2764
|
+
loc = new URL(href);
|
|
2765
|
+
} catch {
|
|
2766
|
+
return void 0;
|
|
2767
|
+
}
|
|
2768
|
+
const email = loc.searchParams.get("email");
|
|
2769
|
+
const phone = loc.searchParams.get("phone");
|
|
2770
|
+
const userId = loc.searchParams.get("user_id");
|
|
2771
|
+
const id = loc.searchParams.get("id");
|
|
2772
|
+
const customRaw = loc.searchParams.get("custom");
|
|
2773
|
+
const identity = {};
|
|
2774
|
+
if (email) identity.email = email;
|
|
2775
|
+
if (phone) identity.phone = phone;
|
|
2776
|
+
if (userId) identity.user_id = userId;
|
|
2777
|
+
if (id) identity.id = id;
|
|
2778
|
+
if (customRaw) {
|
|
2779
|
+
try {
|
|
2780
|
+
const custom = JSON.parse(decodeURIComponent(customRaw));
|
|
2781
|
+
if (typeof custom === "object" && custom !== null) {
|
|
2782
|
+
identity.custom = custom;
|
|
2783
|
+
}
|
|
2784
|
+
} catch {
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
return Object.keys(identity).length > 0 ? identity : void 0;
|
|
2788
|
+
}
|
|
2789
|
+
function captureWebDeepLink() {
|
|
2790
|
+
if (didCapture) return captured;
|
|
2791
|
+
didCapture = true;
|
|
2792
|
+
const stored = readStored2();
|
|
2793
|
+
if (stored) {
|
|
2794
|
+
captured = stored;
|
|
2795
|
+
return captured;
|
|
2796
|
+
}
|
|
2797
|
+
if (typeof window === "undefined" || !window.location) return null;
|
|
2798
|
+
const link = parseUniversalLink(window.location.href);
|
|
2799
|
+
if (link && hasPayload(link)) {
|
|
2800
|
+
captured = link;
|
|
2801
|
+
writeStored2(link);
|
|
2802
|
+
void superlinkClient.reportEvent({
|
|
2803
|
+
type: "opened",
|
|
2804
|
+
click_id: link.click_id,
|
|
2805
|
+
platform: "desktop",
|
|
2806
|
+
properties: { surface: "web" }
|
|
2807
|
+
});
|
|
2808
|
+
}
|
|
2809
|
+
return captured;
|
|
2810
|
+
}
|
|
2811
|
+
function getDeepLink() {
|
|
2812
|
+
if (!didCapture) return captureWebDeepLink();
|
|
2813
|
+
return captured;
|
|
2814
|
+
}
|
|
2815
|
+
function webFingerprint() {
|
|
2816
|
+
const fp = { platform: "desktop" };
|
|
2817
|
+
if (typeof navigator !== "undefined") {
|
|
2818
|
+
if (navigator.userAgent) fp.user_agent = navigator.userAgent;
|
|
2819
|
+
const lang = navigator.language || navigator.languages && navigator.languages[0];
|
|
2820
|
+
if (lang) fp.language = lang;
|
|
2821
|
+
}
|
|
2822
|
+
return fp;
|
|
2823
|
+
}
|
|
2824
|
+
async function identify(identity) {
|
|
2825
|
+
if (!identity || Object.keys(identity).length === 0) return null;
|
|
2826
|
+
const res = await superlinkClient.match({
|
|
2827
|
+
identity,
|
|
2828
|
+
fingerprint: webFingerprint()
|
|
2829
|
+
});
|
|
2830
|
+
if (!res.matched) return null;
|
|
2831
|
+
const link = toDeepLink(res);
|
|
2832
|
+
emitDeferredDeepLink(link);
|
|
2833
|
+
return link;
|
|
2834
|
+
}
|
|
2835
|
+
async function completeFromScan(scanned) {
|
|
2836
|
+
if (!scanned) return null;
|
|
2837
|
+
const res = await superlinkClient.match({
|
|
2838
|
+
qr_token: scanned,
|
|
2839
|
+
fingerprint: webFingerprint()
|
|
2840
|
+
});
|
|
2841
|
+
if (!res.matched) return null;
|
|
2842
|
+
const link = toDeepLink(res);
|
|
2843
|
+
emitDeferredDeepLink(link);
|
|
2844
|
+
return link;
|
|
2845
|
+
}
|
|
2846
|
+
|
|
2847
|
+
// src/superlink/index.ts
|
|
2848
|
+
function initSuperLink(config = {}) {
|
|
2849
|
+
superlinkClient.configure(config);
|
|
2850
|
+
captureWebDeepLink();
|
|
2851
|
+
}
|
|
2852
|
+
|
|
2313
2853
|
// src/index.ts
|
|
2314
2854
|
function installFallbackEnvironment() {
|
|
2315
2855
|
if (getEnvironment()) return;
|
|
@@ -2519,6 +3059,10 @@ var SitePongClient = class {
|
|
|
2519
3059
|
webVitals: config.performance.webVitals,
|
|
2520
3060
|
navigationTiming: config.performance.navigationTiming,
|
|
2521
3061
|
resourceTiming: config.performance.resourceTiming,
|
|
3062
|
+
capturePageLoadTimings: config.performance.capturePageLoadTimings,
|
|
3063
|
+
capturePageRenderTimings: config.performance.capturePageRenderTimings,
|
|
3064
|
+
excludedResourceUrls: config.performance.excludedResourceUrls,
|
|
3065
|
+
resourceNameSanitizer: config.performance.resourceNameSanitizer,
|
|
2522
3066
|
sampleRate: config.performance.sampleRate,
|
|
2523
3067
|
flushInterval: config.performance.flushInterval,
|
|
2524
3068
|
performanceEndpoint: config.performance.performanceEndpoint,
|
|
@@ -3227,7 +3771,7 @@ var areFlagsReady = sitepong.areFlagsReady.bind(sitepong);
|
|
|
3227
3771
|
var refreshFlags = sitepong.refreshFlags.bind(sitepong);
|
|
3228
3772
|
var track = sitepong.track.bind(sitepong);
|
|
3229
3773
|
var trackPageView = sitepong.trackPageView.bind(sitepong);
|
|
3230
|
-
var
|
|
3774
|
+
var identify2 = sitepong.identify.bind(sitepong);
|
|
3231
3775
|
var group = sitepong.group.bind(sitepong);
|
|
3232
3776
|
var resetAnalytics = sitepong.resetAnalytics.bind(sitepong);
|
|
3233
3777
|
var getVisitorId = sitepong.getVisitorId.bind(sitepong);
|
|
@@ -5163,11 +5707,11 @@ function getNotificationsPermission() {
|
|
|
5163
5707
|
return Notification.permission === "granted";
|
|
5164
5708
|
}
|
|
5165
5709
|
function getDeviceAge() {
|
|
5166
|
-
const
|
|
5710
|
+
const STORAGE_KEY5 = "sitepong_device_age";
|
|
5167
5711
|
const result = { visitCount: 1 };
|
|
5168
5712
|
if (typeof localStorage === "undefined") return result;
|
|
5169
5713
|
try {
|
|
5170
|
-
const stored = localStorage.getItem(
|
|
5714
|
+
const stored = localStorage.getItem(STORAGE_KEY5);
|
|
5171
5715
|
if (stored) {
|
|
5172
5716
|
const parsed = JSON.parse(stored);
|
|
5173
5717
|
result.firstSeen = parsed.firstSeen;
|
|
@@ -5175,7 +5719,7 @@ function getDeviceAge() {
|
|
|
5175
5719
|
} else {
|
|
5176
5720
|
result.firstSeen = (/* @__PURE__ */ new Date()).toISOString();
|
|
5177
5721
|
}
|
|
5178
|
-
localStorage.setItem(
|
|
5722
|
+
localStorage.setItem(STORAGE_KEY5, JSON.stringify({
|
|
5179
5723
|
firstSeen: result.firstSeen,
|
|
5180
5724
|
visitCount: result.visitCount
|
|
5181
5725
|
}));
|
|
@@ -5957,6 +6501,6 @@ registerWebManagerFactories({
|
|
|
5957
6501
|
createPerformance: (cfg) => new PerformanceManager(cfg)
|
|
5958
6502
|
});
|
|
5959
6503
|
|
|
5960
|
-
export { TracePropagator, addBreadcrumb, areFlagsReady, captureError, captureMessage, clearAnonymousId, clearUser, sitepong as client, createTraceContext, cronCheckin, cronStart, cronWrap, dbTrack, dbTrackSync, src_default as default, endSpan, endTransaction, extractTrace, flush, flushMetrics, flushProfiles, generateSpanId, generateTraceId, getAllFlags, getAnonymousId, getDbNPlusOnePatterns, getDbQueryCount, getDeviceSignals, getFlag, getFraudCheck, getLatestProfile, getProfiles, getRemoteConfig, getReplaySessionId, getVariant, getVariantPayload2 as getVariantPayload, getVisitorId, getWebVitals, group, identify, init, initRN, isInitialized, isRemoteConfigFeatureEnabled, isReplayRecording, metricDistribution, metricGauge, metricHistogram, metricIncrement, metricStartTimer, metricTime, onRemoteConfigChange, profile, propagateTrace, refreshFlags, registerIdentifyHook, registerWebManagerFactories, resetAnalytics, resetDbQueryCount, setAnonymousId, setContext, setCurrentScreen, setEnvironment, setRNGetCurrentScreen, setTags, setUser, startProfileSpan, startReplay, startSpan, startTransaction, stopReplay, track, trackPageView, waitForFlags };
|
|
6504
|
+
export { DEFAULT_SUPERLINK_ENDPOINT, SuperLinkClient, TracePropagator, addBreadcrumb, areFlagsReady, captureError, captureMessage, captureWebDeepLink, clearAnonymousId, clearUser, sitepong as client, completeFromScan, createTraceContext, cronCheckin, cronStart, cronWrap, dbTrack, dbTrackSync, src_default as default, endSpan, endTransaction, extractIdentityMetadata, extractTrace, flush, flushMetrics, flushProfiles, generateSpanId, generateTraceId, getAllFlags, getAnonymousId, getDbNPlusOnePatterns, getDbQueryCount, getDeepLink, getDeviceSignals, getFlag, getFraudCheck, getLatestProfile, getMatchedDeepLink, getProfiles, getRemoteConfig, getReplaySessionId, getVariant, getVariantPayload2 as getVariantPayload, getVisitorId, getWebVitals, group, identify2 as identify, init, initRN, initSuperLink, isInitialized, isRemoteConfigFeatureEnabled, isReplayRecording, metricDistribution, metricGauge, metricHistogram, metricIncrement, metricStartTimer, metricTime, onDeferredDeepLink, onRemoteConfigChange, parseUniversalLink, profile, propagateTrace, refreshFlags, registerIdentifyHook, registerWebManagerFactories, resetAnalytics, resetDbQueryCount, setAnonymousId, setContext, setCurrentScreen, setEnvironment, setRNGetCurrentScreen, setTags, setUser, startProfileSpan, startReplay, startSpan, startTransaction, stopReplay, superlinkClient, identify as superlinkIdentify, track, trackPageView, waitForFlags, writeClipboardToken };
|
|
5961
6505
|
//# sourceMappingURL=web.mjs.map
|
|
5962
6506
|
//# sourceMappingURL=web.mjs.map
|