sitepong 0.1.13 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ require('web-vitals');
6
+
5
7
  // src/flags/anonymous-id.ts
6
8
  var STORAGE_KEY = "sitepong_anonymous_id";
7
9
  function generateUUID() {
@@ -1907,6 +1909,292 @@ var TracePropagator = class {
1907
1909
  }
1908
1910
  };
1909
1911
 
1912
+ // src/superlink/client.ts
1913
+ var DEFAULT_SUPERLINK_ENDPOINT = "https://pongl.ink";
1914
+ var SuperLinkClient = class {
1915
+ constructor(config = {}) {
1916
+ this.config = {
1917
+ endpoint: stripTrailingSlash(config.endpoint || DEFAULT_SUPERLINK_ENDPOINT),
1918
+ appId: config.appId,
1919
+ installId: config.installId,
1920
+ debug: config.debug ?? false
1921
+ };
1922
+ }
1923
+ /** Replace config in place (used by init() so module-level helpers see updates). */
1924
+ configure(config) {
1925
+ if (config.endpoint) this.config.endpoint = stripTrailingSlash(config.endpoint);
1926
+ if (config.appId !== void 0) this.config.appId = config.appId;
1927
+ if (config.installId !== void 0) this.config.installId = config.installId;
1928
+ if (config.debug !== void 0) this.config.debug = config.debug;
1929
+ }
1930
+ log(...args) {
1931
+ if (this.config.debug) console.warn("[SuperLink]", ...args);
1932
+ }
1933
+ /**
1934
+ * POST /match — ask the redirect engine to resolve a deferred deep link from
1935
+ * a click token (Android referrer / iOS clipboard) and/or a device
1936
+ * fingerprint. Returns `{ matched: false }` on any error.
1937
+ */
1938
+ async match(body) {
1939
+ const payload = {
1940
+ ...body,
1941
+ install_id: body.install_id ?? this.config.installId
1942
+ };
1943
+ try {
1944
+ const res = await fetch(`${this.config.endpoint}/match`, {
1945
+ method: "POST",
1946
+ headers: { "Content-Type": "application/json" },
1947
+ body: JSON.stringify(payload)
1948
+ });
1949
+ if (!res.ok) {
1950
+ this.log("match failed", res.status);
1951
+ return { matched: false };
1952
+ }
1953
+ const data = await res.json();
1954
+ return data ?? { matched: false };
1955
+ } catch (err) {
1956
+ this.log("match error", err);
1957
+ return { matched: false };
1958
+ }
1959
+ }
1960
+ /**
1961
+ * POST /events — report a lifecycle event (opened / converted) back to the
1962
+ * redirect engine, which fans out to analytics + webhooks. Best-effort.
1963
+ */
1964
+ async reportEvent(input) {
1965
+ try {
1966
+ const res = await fetch(`${this.config.endpoint}/events`, {
1967
+ method: "POST",
1968
+ headers: { "Content-Type": "application/json" },
1969
+ body: JSON.stringify({
1970
+ app_id: this.config.appId,
1971
+ install_id: this.config.installId,
1972
+ ...input
1973
+ })
1974
+ });
1975
+ if (!res.ok) this.log("event failed", input.type, res.status);
1976
+ return res.ok;
1977
+ } catch (err) {
1978
+ this.log("event error", err);
1979
+ return false;
1980
+ }
1981
+ }
1982
+ };
1983
+ function stripTrailingSlash(url) {
1984
+ return url.endsWith("/") ? url.slice(0, -1) : url;
1985
+ }
1986
+ var superlinkClient = new SuperLinkClient();
1987
+
1988
+ // src/superlink/parse.ts
1989
+ var UTM_KEYS = [
1990
+ ["source", "utm_source"],
1991
+ ["medium", "utm_medium"],
1992
+ ["campaign", "utm_campaign"],
1993
+ ["term", "utm_term"],
1994
+ ["content", "utm_content"]
1995
+ ];
1996
+ function parseUniversalLink(url) {
1997
+ let parsed;
1998
+ try {
1999
+ parsed = new URL(url);
2000
+ } catch {
2001
+ return null;
2002
+ }
2003
+ const params = parsed.searchParams;
2004
+ const utm = {};
2005
+ for (const [key, queryKey] of UTM_KEYS) {
2006
+ const value = params.get(queryKey);
2007
+ if (value) utm[key] = value;
2008
+ }
2009
+ const referral = {};
2010
+ const deep_link_data = {};
2011
+ params.forEach((value, key) => {
2012
+ if (key.startsWith("r_")) {
2013
+ referral[key.slice(2)] = value;
2014
+ } else if (key.startsWith("~")) {
2015
+ deep_link_data[key.slice(1)] = value;
2016
+ }
2017
+ });
2018
+ const explicitPath = params.get("$deep_link_path") ?? params.get("dlp");
2019
+ const deep_link_path = explicitPath ?? (parsed.pathname && parsed.pathname !== "/" ? parsed.pathname : null);
2020
+ return {
2021
+ deep_link_path,
2022
+ deep_link_data,
2023
+ utm,
2024
+ referral,
2025
+ click_id: params.get("click_id"),
2026
+ match_type: "none",
2027
+ confidence: 1
2028
+ };
2029
+ }
2030
+
2031
+ // src/superlink/deferred.ts
2032
+ var handlers = /* @__PURE__ */ new Set();
2033
+ var lastMatched = null;
2034
+ function toDeepLink(res) {
2035
+ return {
2036
+ deep_link_path: res.deep_link_path ?? null,
2037
+ deep_link_data: res.deep_link_data ?? {},
2038
+ utm: res.utm ?? {},
2039
+ referral: res.referral ?? {},
2040
+ click_id: res.click_id ?? null,
2041
+ match_type: res.match_type ?? "fingerprint",
2042
+ confidence: res.confidence ?? (res.match_type && res.match_type !== "none" ? 1 : 0)
2043
+ };
2044
+ }
2045
+ function emitDeferredDeepLink(link) {
2046
+ lastMatched = link;
2047
+ for (const handler of handlers) {
2048
+ try {
2049
+ handler(link);
2050
+ } catch (err) {
2051
+ if (superlinkClient.config.debug) console.warn("[SuperLink] handler threw", err);
2052
+ }
2053
+ }
2054
+ }
2055
+ function onDeferredDeepLink(handler) {
2056
+ handlers.add(handler);
2057
+ if (lastMatched) {
2058
+ try {
2059
+ handler(lastMatched);
2060
+ } catch {
2061
+ }
2062
+ }
2063
+ return () => {
2064
+ handlers.delete(handler);
2065
+ };
2066
+ }
2067
+ function getMatchedDeepLink() {
2068
+ return lastMatched;
2069
+ }
2070
+
2071
+ // src/superlink/web.ts
2072
+ var STORAGE_KEY3 = "sp_superlink";
2073
+ var captured = null;
2074
+ var didCapture = false;
2075
+ function readStored() {
2076
+ if (typeof sessionStorage === "undefined") return null;
2077
+ try {
2078
+ const raw = sessionStorage.getItem(STORAGE_KEY3);
2079
+ if (!raw) return null;
2080
+ const parsed = JSON.parse(raw);
2081
+ return parsed && typeof parsed === "object" ? parsed : null;
2082
+ } catch {
2083
+ return null;
2084
+ }
2085
+ }
2086
+ function writeStored(link) {
2087
+ if (typeof sessionStorage === "undefined") return;
2088
+ try {
2089
+ sessionStorage.setItem(STORAGE_KEY3, JSON.stringify(link));
2090
+ } catch {
2091
+ }
2092
+ }
2093
+ function hasPayload(link) {
2094
+ return Boolean(
2095
+ 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
2096
+ );
2097
+ }
2098
+ function writeClipboardToken(clickId) {
2099
+ if (typeof navigator === "undefined" || !navigator.clipboard) return;
2100
+ const url = `${superlinkClient.config.endpoint}/c/${clickId}`;
2101
+ navigator.clipboard.writeText(url).catch(() => {
2102
+ });
2103
+ }
2104
+ function extractIdentityMetadata(url) {
2105
+ const href = url ?? (typeof window !== "undefined" && window.location ? window.location.href : null);
2106
+ if (!href) return void 0;
2107
+ let loc;
2108
+ try {
2109
+ loc = new URL(href);
2110
+ } catch {
2111
+ return void 0;
2112
+ }
2113
+ const email = loc.searchParams.get("email");
2114
+ const phone = loc.searchParams.get("phone");
2115
+ const userId = loc.searchParams.get("user_id");
2116
+ const id = loc.searchParams.get("id");
2117
+ const customRaw = loc.searchParams.get("custom");
2118
+ const identity = {};
2119
+ if (email) identity.email = email;
2120
+ if (phone) identity.phone = phone;
2121
+ if (userId) identity.user_id = userId;
2122
+ if (id) identity.id = id;
2123
+ if (customRaw) {
2124
+ try {
2125
+ const custom = JSON.parse(decodeURIComponent(customRaw));
2126
+ if (typeof custom === "object" && custom !== null) {
2127
+ identity.custom = custom;
2128
+ }
2129
+ } catch {
2130
+ }
2131
+ }
2132
+ return Object.keys(identity).length > 0 ? identity : void 0;
2133
+ }
2134
+ function captureWebDeepLink() {
2135
+ if (didCapture) return captured;
2136
+ didCapture = true;
2137
+ const stored = readStored();
2138
+ if (stored) {
2139
+ captured = stored;
2140
+ return captured;
2141
+ }
2142
+ if (typeof window === "undefined" || !window.location) return null;
2143
+ const link = parseUniversalLink(window.location.href);
2144
+ if (link && hasPayload(link)) {
2145
+ captured = link;
2146
+ writeStored(link);
2147
+ void superlinkClient.reportEvent({
2148
+ type: "opened",
2149
+ click_id: link.click_id,
2150
+ platform: "desktop",
2151
+ properties: { surface: "web" }
2152
+ });
2153
+ }
2154
+ return captured;
2155
+ }
2156
+ function getDeepLink() {
2157
+ if (!didCapture) return captureWebDeepLink();
2158
+ return captured;
2159
+ }
2160
+ function webFingerprint() {
2161
+ const fp = { platform: "desktop" };
2162
+ if (typeof navigator !== "undefined") {
2163
+ if (navigator.userAgent) fp.user_agent = navigator.userAgent;
2164
+ const lang = navigator.language || navigator.languages && navigator.languages[0];
2165
+ if (lang) fp.language = lang;
2166
+ }
2167
+ return fp;
2168
+ }
2169
+ async function identify(identity) {
2170
+ if (!identity || Object.keys(identity).length === 0) return null;
2171
+ const res = await superlinkClient.match({
2172
+ identity,
2173
+ fingerprint: webFingerprint()
2174
+ });
2175
+ if (!res.matched) return null;
2176
+ const link = toDeepLink(res);
2177
+ emitDeferredDeepLink(link);
2178
+ return link;
2179
+ }
2180
+ async function completeFromScan(scanned) {
2181
+ if (!scanned) return null;
2182
+ const res = await superlinkClient.match({
2183
+ qr_token: scanned,
2184
+ fingerprint: webFingerprint()
2185
+ });
2186
+ if (!res.matched) return null;
2187
+ const link = toDeepLink(res);
2188
+ emitDeferredDeepLink(link);
2189
+ return link;
2190
+ }
2191
+
2192
+ // src/superlink/index.ts
2193
+ function initSuperLink(config = {}) {
2194
+ superlinkClient.configure(config);
2195
+ captureWebDeepLink();
2196
+ }
2197
+
1910
2198
  // src/index.ts
1911
2199
  function installFallbackEnvironment() {
1912
2200
  if (getEnvironment()) return;
@@ -2116,6 +2404,10 @@ var SitePongClient = class {
2116
2404
  webVitals: config.performance.webVitals,
2117
2405
  navigationTiming: config.performance.navigationTiming,
2118
2406
  resourceTiming: config.performance.resourceTiming,
2407
+ capturePageLoadTimings: config.performance.capturePageLoadTimings,
2408
+ capturePageRenderTimings: config.performance.capturePageRenderTimings,
2409
+ excludedResourceUrls: config.performance.excludedResourceUrls,
2410
+ resourceNameSanitizer: config.performance.resourceNameSanitizer,
2119
2411
  sampleRate: config.performance.sampleRate,
2120
2412
  flushInterval: config.performance.flushInterval,
2121
2413
  performanceEndpoint: config.performance.performanceEndpoint,
@@ -2824,7 +3116,7 @@ var areFlagsReady = sitepong.areFlagsReady.bind(sitepong);
2824
3116
  var refreshFlags = sitepong.refreshFlags.bind(sitepong);
2825
3117
  var track = sitepong.track.bind(sitepong);
2826
3118
  var trackPageView = sitepong.trackPageView.bind(sitepong);
2827
- var identify = sitepong.identify.bind(sitepong);
3119
+ var identify2 = sitepong.identify.bind(sitepong);
2828
3120
  var group = sitepong.group.bind(sitepong);
2829
3121
  var resetAnalytics = sitepong.resetAnalytics.bind(sitepong);
2830
3122
  var getVisitorId = sitepong.getVisitorId.bind(sitepong);
@@ -2865,14 +3157,18 @@ var onRemoteConfigChange = sitepong.onRemoteConfigChange.bind(sitepong);
2865
3157
  var registerIdentifyHook = sitepong.registerIdentifyHook.bind(sitepong);
2866
3158
  var src_default = sitepong;
2867
3159
 
3160
+ exports.DEFAULT_SUPERLINK_ENDPOINT = DEFAULT_SUPERLINK_ENDPOINT;
3161
+ exports.SuperLinkClient = SuperLinkClient;
2868
3162
  exports.TracePropagator = TracePropagator;
2869
3163
  exports.addBreadcrumb = addBreadcrumb;
2870
3164
  exports.areFlagsReady = areFlagsReady;
2871
3165
  exports.captureError = captureError;
2872
3166
  exports.captureMessage = captureMessage;
3167
+ exports.captureWebDeepLink = captureWebDeepLink;
2873
3168
  exports.clearAnonymousId = clearAnonymousId;
2874
3169
  exports.clearUser = clearUser;
2875
3170
  exports.client = sitepong;
3171
+ exports.completeFromScan = completeFromScan;
2876
3172
  exports.createTraceContext = createTraceContext;
2877
3173
  exports.cronCheckin = cronCheckin;
2878
3174
  exports.cronStart = cronStart;
@@ -2882,6 +3178,7 @@ exports.dbTrackSync = dbTrackSync;
2882
3178
  exports.default = src_default;
2883
3179
  exports.endSpan = endSpan;
2884
3180
  exports.endTransaction = endTransaction;
3181
+ exports.extractIdentityMetadata = extractIdentityMetadata;
2885
3182
  exports.extractTrace = extractTrace;
2886
3183
  exports.flush = flush;
2887
3184
  exports.flushMetrics = flushMetrics;
@@ -2892,10 +3189,12 @@ exports.getAllFlags = getAllFlags;
2892
3189
  exports.getAnonymousId = getAnonymousId;
2893
3190
  exports.getDbNPlusOnePatterns = getDbNPlusOnePatterns;
2894
3191
  exports.getDbQueryCount = getDbQueryCount;
3192
+ exports.getDeepLink = getDeepLink;
2895
3193
  exports.getDeviceSignals = getDeviceSignals;
2896
3194
  exports.getFlag = getFlag;
2897
3195
  exports.getFraudCheck = getFraudCheck;
2898
3196
  exports.getLatestProfile = getLatestProfile;
3197
+ exports.getMatchedDeepLink = getMatchedDeepLink;
2899
3198
  exports.getProfiles = getProfiles;
2900
3199
  exports.getRemoteConfig = getRemoteConfig;
2901
3200
  exports.getReplaySessionId = getReplaySessionId;
@@ -2904,9 +3203,10 @@ exports.getVariantPayload = getVariantPayload2;
2904
3203
  exports.getVisitorId = getVisitorId;
2905
3204
  exports.getWebVitals = getWebVitals;
2906
3205
  exports.group = group;
2907
- exports.identify = identify;
3206
+ exports.identify = identify2;
2908
3207
  exports.init = init;
2909
3208
  exports.initRN = initRN;
3209
+ exports.initSuperLink = initSuperLink;
2910
3210
  exports.isInitialized = isInitialized;
2911
3211
  exports.isRemoteConfigFeatureEnabled = isRemoteConfigFeatureEnabled;
2912
3212
  exports.isReplayRecording = isReplayRecording;
@@ -2916,7 +3216,9 @@ exports.metricHistogram = metricHistogram;
2916
3216
  exports.metricIncrement = metricIncrement;
2917
3217
  exports.metricStartTimer = metricStartTimer;
2918
3218
  exports.metricTime = metricTime;
3219
+ exports.onDeferredDeepLink = onDeferredDeepLink;
2919
3220
  exports.onRemoteConfigChange = onRemoteConfigChange;
3221
+ exports.parseUniversalLink = parseUniversalLink;
2920
3222
  exports.profile = profile;
2921
3223
  exports.propagateTrace = propagateTrace;
2922
3224
  exports.refreshFlags = refreshFlags;
@@ -2936,8 +3238,11 @@ exports.startReplay = startReplay;
2936
3238
  exports.startSpan = startSpan;
2937
3239
  exports.startTransaction = startTransaction;
2938
3240
  exports.stopReplay = stopReplay;
3241
+ exports.superlinkClient = superlinkClient;
3242
+ exports.superlinkIdentify = identify;
2939
3243
  exports.track = track;
2940
3244
  exports.trackPageView = trackPageView;
2941
3245
  exports.waitForFlags = waitForFlags;
3246
+ exports.writeClipboardToken = writeClipboardToken;
2942
3247
  //# sourceMappingURL=index.js.map
2943
3248
  //# sourceMappingURL=index.js.map