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