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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { R as ReplayConfig, T as TrackProperties, U as UserTraits, G as GroupTraits } from './types-BEqbz0tw.js';
2
- export { a as ReplayEvent } from './types-BEqbz0tw.js';
1
+ import { R as ReplayConfig, T as TrackProperties, U as UserTraits, G as GroupTraits } from './types-DPINdOQW.js';
2
+ export { a as ReplayEvent } from './types-DPINdOQW.js';
3
3
 
4
4
  /**
5
5
  * Fingerprint Types
@@ -225,12 +225,20 @@ interface PerformanceConfig {
225
225
  apiKey: string;
226
226
  endpoint?: string;
227
227
  enabled?: boolean;
228
- /** Collect Web Vitals (default: true) */
228
+ /** Collect Web Vitals via web-vitals library (default: true) */
229
229
  webVitals?: boolean;
230
230
  /** Report navigation timing (default: true) */
231
231
  navigationTiming?: boolean;
232
- /** Report resource timing (default: false) */
232
+ /** Report resource timing with detailed breakdowns (default: true) */
233
233
  resourceTiming?: boolean;
234
+ /** Capture page load timing milestones (default: true) */
235
+ capturePageLoadTimings?: boolean;
236
+ /** Capture page render timing: Speed Index, TTI, Visually Complete (default: true) */
237
+ capturePageRenderTimings?: boolean;
238
+ /** URL prefixes to exclude from resource timing collection */
239
+ excludedResourceUrls?: string[];
240
+ /** Transform resource URLs before reporting (strip tokens, etc.) */
241
+ resourceNameSanitizer?: (url: string) => string;
234
242
  /** Custom endpoint for performance data */
235
243
  performanceEndpoint?: string;
236
244
  /** Flush interval in ms (default: 10000) */
@@ -241,12 +249,29 @@ interface PerformanceConfig {
241
249
  }
242
250
  interface WebVitals {
243
251
  lcp?: number;
244
- fid?: number;
245
252
  cls?: number;
246
253
  fcp?: number;
247
254
  ttfb?: number;
248
255
  inp?: number;
249
256
  }
257
+ interface ResourceTimingBreakdown {
258
+ queueing: number;
259
+ dnsLookup: number;
260
+ initialConnection: number;
261
+ ssl: number;
262
+ ttfb: number;
263
+ contentDownload: number;
264
+ total: number;
265
+ stalled: number;
266
+ cached: boolean;
267
+ failed: boolean;
268
+ responseStatus: number;
269
+ headerSize: number;
270
+ encodedBodySize: number;
271
+ decodedBodySize: number;
272
+ transferSize: number;
273
+ initiatorType: string;
274
+ }
250
275
  interface PerformanceSpan {
251
276
  id: string;
252
277
  name: string;
@@ -276,31 +301,25 @@ declare class PerformanceManager {
276
301
  private vitals;
277
302
  private activeTransactions;
278
303
  private sampled;
304
+ private resourceObserver;
305
+ private resourceTimeMap;
306
+ private resourceCount;
307
+ private pageLoadTimer;
308
+ private pageRenderTimer;
279
309
  constructor(config: PerformanceConfig);
280
310
  init(): void;
281
- /**
282
- * Start a custom transaction for measuring operations
283
- */
311
+ private initWebVitals;
312
+ private initResourceTiming;
313
+ private isServiceURL;
314
+ private processResourceEntry;
315
+ private initPageLoadTiming;
316
+ private initPageRenderTiming;
284
317
  startTransaction(name: string, data?: Record<string, unknown>): string;
285
- /**
286
- * End a transaction and report it
287
- */
288
318
  endTransaction(id: string, status?: 'ok' | 'error'): void;
289
- /**
290
- * Start a span within a transaction
291
- */
292
319
  startSpan(transactionId: string, name: string, data?: Record<string, unknown>): string;
293
- /**
294
- * End a span
295
- */
296
320
  endSpan(transactionId: string, spanId: string, status?: 'ok' | 'error'): void;
297
- /**
298
- * Get current Web Vitals
299
- */
300
321
  getVitals(): WebVitals;
301
322
  destroy(): void;
302
- private observeWebVitals;
303
- private collectNavigationTiming;
304
323
  private reportVital;
305
324
  private addMetric;
306
325
  private startFlushTimer;
@@ -632,6 +651,311 @@ interface DatabaseTrackerConfig {
632
651
  redactParams?: boolean;
633
652
  }
634
653
 
654
+ /**
655
+ * SuperLink — deferred deep linking / smart links (OneLink/Branch-style).
656
+ *
657
+ * These types are platform-agnostic and shared between the web capture path
658
+ * and the React Native deferred-attribution path. They mirror the database
659
+ * schema (see supabase/migrations/*_superlink.sql): the redirect engine logs
660
+ * clicks + device fingerprints, and the mobile SDK matches on first launch to
661
+ * deliver the original deep link across the install gap.
662
+ */
663
+ /**
664
+ * UTM parameters carried on a SuperLink. Keyed without the `utm_` prefix —
665
+ * the redirect URL's `utm_source`/`utm_medium`/… map to `source`/`medium`/…
666
+ * (self-contained so the SuperLink module has no cross-module dependencies).
667
+ */
668
+ interface UtmParams {
669
+ source?: string;
670
+ medium?: string;
671
+ campaign?: string;
672
+ term?: string;
673
+ content?: string;
674
+ }
675
+ /** Platforms recognised by the redirect engine (matches superlink_platform). */
676
+ type SuperLinkPlatform = 'ios' | 'android' | 'desktop' | 'other';
677
+ /** How a deferred click was matched to an install (matches superlink_match_type). */
678
+ type SuperLinkMatchType = 'referrer' | 'clipboard' | 'qr' | 'identity' | 'fingerprint' | 'none';
679
+ /** Lifecycle event types (matches superlink_event_type). */
680
+ type SuperLinkEventType = 'clicked' | 'installed' | 'opened' | 'converted';
681
+ /**
682
+ * Configuration for the SuperLink client.
683
+ */
684
+ interface SuperLinkConfig {
685
+ /** Redirect engine base URL. Defaults to the shared short domain. */
686
+ endpoint?: string;
687
+ /** Optional SuperLink app id (superlink_apps.id) for store-URL / AASA context. */
688
+ appId?: string;
689
+ /** Stable per-install id reported at match time (superlink_clicks.install_id). */
690
+ installId?: string;
691
+ /** Emit verbose diagnostics to the console. */
692
+ debug?: boolean;
693
+ }
694
+ /**
695
+ * Resolved deep link payload delivered to the app, whether captured directly
696
+ * on the web (inbound params), via a Universal Link / App Link open, or matched
697
+ * deferentially on first launch after an install.
698
+ */
699
+ interface SuperLinkDeepLink {
700
+ /** In-app route, e.g. "/products/42" (superlink_links.deep_link_path). */
701
+ deep_link_path: string | null;
702
+ /** Arbitrary payload delivered on open (superlink_links.deep_link_data). */
703
+ deep_link_data: Record<string, unknown>;
704
+ /** Campaign params carried from the click URL. */
705
+ utm: UtmParams;
706
+ /** Affiliate / referral params carried from the click URL. */
707
+ referral: Record<string, unknown>;
708
+ /** Opaque click token, when known (superlink_clicks.click_id). */
709
+ click_id?: string | null;
710
+ /** How this link was resolved. */
711
+ match_type: SuperLinkMatchType;
712
+ /** 0..1 confidence — deterministic matches are 1, fingerprint matches lower. */
713
+ confidence: number;
714
+ }
715
+ /** Server response to POST /match. */
716
+ interface SuperLinkMatchResponse {
717
+ matched: boolean;
718
+ click_id?: string | null;
719
+ link_id?: string | null;
720
+ deep_link_path?: string | null;
721
+ deep_link_data?: Record<string, unknown>;
722
+ utm?: UtmParams;
723
+ referral?: Record<string, unknown>;
724
+ match_type?: SuperLinkMatchType;
725
+ confidence?: number;
726
+ }
727
+ /** Handler invoked with a resolved deferred deep link. */
728
+ type DeferredDeepLinkHandler = (link: SuperLinkDeepLink) => void;
729
+ /**
730
+ * Device fingerprint signals POSTed to /match. Mirrors the fingerprint columns
731
+ * on superlink_clicks. All fields are best-effort and optional.
732
+ */
733
+ interface SuperLinkFingerprint {
734
+ platform: SuperLinkPlatform;
735
+ os?: string;
736
+ os_version?: string;
737
+ device_model?: string;
738
+ /** Browser name/UA, when known (web/desktop). */
739
+ browser?: string;
740
+ /** Coarse device class reported to the engine. */
741
+ device_type?: string;
742
+ /** Client IP, when the caller knows it (engine usually fills this in). */
743
+ ip?: string;
744
+ /** Raw user-agent string (web/desktop). */
745
+ user_agent?: string;
746
+ /** BCP-47 locale tag. */
747
+ language?: string;
748
+ }
749
+ /** Identity metadata for high-confidence matching against a click's metadata jsonb. */
750
+ interface SuperLinkIdentityMetadata {
751
+ /** User-supplied email for matching. */
752
+ email?: string;
753
+ /** User-supplied phone number for matching. */
754
+ phone?: string;
755
+ /** App-level user id for matching. */
756
+ user_id?: string;
757
+ /** Generic id for matching. */
758
+ id?: string;
759
+ /** Arbitrary user-provided attributes for custom matching. */
760
+ custom?: Record<string, unknown>;
761
+ }
762
+ /**
763
+ * Request body for POST /match. All fields are optional; the engine resolves in
764
+ * the order referrer → clipboard_token → qr_token → identity → fingerprint
765
+ * (first hit wins, best→worst).
766
+ */
767
+ interface SuperLinkMatchRequest {
768
+ install_id?: string;
769
+ /** Android Play Install Referrer click_id (deterministic). */
770
+ referrer?: string;
771
+ /**
772
+ * iOS clipboard value: a raw click_id, "pongl.ink/c/<click_id>", or
773
+ * "https://pongl.ink/c/<click_id>". Passed through raw — the engine parses it.
774
+ */
775
+ clipboard_token?: string;
776
+ /**
777
+ * Scanned QR payload: a click-token URL (/c/<id>), a raw click_id, a link URL
778
+ * (pongl.ink/<slug>), or a bare <slug>. Passed through raw.
779
+ */
780
+ qr_token?: string;
781
+ /** Identity metadata matched against the click's metadata jsonb. */
782
+ identity?: SuperLinkIdentityMetadata;
783
+ fingerprint?: SuperLinkFingerprint;
784
+ }
785
+
786
+ /**
787
+ * SuperLink core client — platform-agnostic.
788
+ *
789
+ * Holds the configured endpoint + app context and exposes thin POST helpers
790
+ * for the redirect engine's /match and /events routes. Both the web capture
791
+ * path and the React Native deferred-attribution path share this instance.
792
+ *
793
+ * Uses the global `fetch` (present on browser, RN, and Node 18+) directly to
794
+ * avoid pulling in any DOM-only transport. All network calls are best-effort
795
+ * and never throw.
796
+ */
797
+
798
+ /** Default shared short domain / redirect engine. */
799
+ declare const DEFAULT_SUPERLINK_ENDPOINT = "https://pongl.ink";
800
+ interface ResolvedSuperLinkConfig {
801
+ endpoint: string;
802
+ appId?: string;
803
+ installId?: string;
804
+ debug: boolean;
805
+ }
806
+ declare class SuperLinkClient {
807
+ config: ResolvedSuperLinkConfig;
808
+ constructor(config?: SuperLinkConfig);
809
+ /** Replace config in place (used by init() so module-level helpers see updates). */
810
+ configure(config: SuperLinkConfig): void;
811
+ private log;
812
+ /**
813
+ * POST /match — ask the redirect engine to resolve a deferred deep link from
814
+ * a click token (Android referrer / iOS clipboard) and/or a device
815
+ * fingerprint. Returns `{ matched: false }` on any error.
816
+ */
817
+ match(body: SuperLinkMatchRequest): Promise<SuperLinkMatchResponse>;
818
+ /**
819
+ * POST /events — report a lifecycle event (opened / converted) back to the
820
+ * redirect engine, which fans out to analytics + webhooks. Best-effort.
821
+ */
822
+ reportEvent(input: {
823
+ type: SuperLinkEventType;
824
+ click_id?: string | null;
825
+ link_id?: string | null;
826
+ platform?: SuperLinkPlatform;
827
+ match_type?: SuperLinkMatchType;
828
+ properties?: Record<string, unknown>;
829
+ }): Promise<boolean>;
830
+ }
831
+ /** The process-wide SuperLink client. */
832
+ declare const superlinkClient: SuperLinkClient;
833
+
834
+ /**
835
+ * SuperLink web capture.
836
+ *
837
+ * On first load, captures inbound deep-link params from the current location
838
+ * (a direct SuperLink open in the browser, or a query-decorated landing) and
839
+ * exposes them via getDeepLink(). The captured payload is cached for the rest
840
+ * of the session so repeated reads are stable.
841
+ *
842
+ * Guards every `window`/`sessionStorage` access so importing this module from a
843
+ * non-DOM bundle is harmless.
844
+ */
845
+
846
+ /**
847
+ * Write a click token to the clipboard in URL form, for handoff to iOS app on install.
848
+ * Called by the interstitial right before redirect to App Store.
849
+ */
850
+ declare function writeClipboardToken(clickId: string): void;
851
+ /**
852
+ * Extract identity metadata from URL query params (?email=&phone=&custom=json).
853
+ * Used to seed the deferred link match with user-provided attributes.
854
+ */
855
+ declare function extractIdentityMetadata(url?: string): SuperLinkIdentityMetadata | undefined;
856
+ /**
857
+ * Capture inbound deep-link params from the current page URL. Idempotent: only
858
+ * the first call of the session parses; later calls return the cached payload.
859
+ */
860
+ declare function captureWebDeepLink(): SuperLinkDeepLink | null;
861
+ /**
862
+ * Return the captured inbound deep link for this session, capturing lazily on
863
+ * first call. Returns null when no SuperLink params were present.
864
+ */
865
+ declare function getDeepLink(): SuperLinkDeepLink | null;
866
+ /**
867
+ * Recover a deferred deep link AFTER the user provides an email/phone (or other
868
+ * identity) at signup. POSTs /match with { identity, install_id, fingerprint }
869
+ * so the engine can match the supplied identity against an unmatched click's
870
+ * metadata. Fires onDeferredDeepLink on a hit. Returns the resolved deep link,
871
+ * or null. Best-effort: never throws.
872
+ *
873
+ * @example
874
+ * ```ts
875
+ * import { identify } from 'sitepong';
876
+ * await identify({ email: user.email, user_id: user.id });
877
+ * ```
878
+ */
879
+ declare function identify$1(identity: SuperLinkIdentityMetadata): Promise<SuperLinkDeepLink | null>;
880
+ /**
881
+ * Complete attribution from a scanned QR payload. POSTs /match with
882
+ * { qr_token: scanned, install_id } — the raw scanned string is passed straight
883
+ * through, and the engine parses a click-token URL (/c/<id>), a raw click_id, a
884
+ * link URL (pongl.ink/<slug>), or a bare <slug>. Fires onDeferredDeepLink on a
885
+ * hit. Returns the resolved deep link, or null. Best-effort: never throws.
886
+ *
887
+ * @example
888
+ * ```ts
889
+ * import { completeFromScan } from 'sitepong';
890
+ * const link = await completeFromScan(qrCodeValue);
891
+ * ```
892
+ */
893
+ declare function completeFromScan(scanned: string): Promise<SuperLinkDeepLink | null>;
894
+
895
+ /**
896
+ * SuperLink deferred-deep-link registry — platform-agnostic.
897
+ *
898
+ * Holds the shared onDeferredDeepLink handler set, the cached last match, and
899
+ * the SuperLinkMatchResponse → SuperLinkDeepLink normaliser. Both the web/node
900
+ * recovery path (identify / completeFromScan) and the React Native first-launch
901
+ * attribution path emit through here so a single handler set sees every match.
902
+ */
903
+
904
+ /**
905
+ * Register a handler fired when a deferred deep link is matched (first-launch
906
+ * attribution, identify(), or completeFromScan()). If a match already happened
907
+ * before registration, the handler is invoked immediately with the cached
908
+ * payload. Returns an unsubscribe fn.
909
+ */
910
+ declare function onDeferredDeepLink(handler: DeferredDeepLinkHandler): () => void;
911
+ /** The deferred deep link matched so far this process, if any. */
912
+ declare function getMatchedDeepLink(): SuperLinkDeepLink | null;
913
+
914
+ /**
915
+ * SuperLink URL parsing — platform-agnostic.
916
+ *
917
+ * Extracts the deep link payload encoded in a SuperLink URL: the path, any
918
+ * `~`-prefixed deep link data, UTM params, and `r_`-prefixed referral params.
919
+ * Works on both inbound web URLs and Universal Link / App Link opens. Uses the
920
+ * WHATWG `URL`, which is available on browser, RN (Hermes), and Node.
921
+ */
922
+
923
+ /**
924
+ * Parse a SuperLink (or Universal/App Link) URL into a deep link payload.
925
+ * Returns null if the URL can't be parsed.
926
+ *
927
+ * Conventions carried in the query string:
928
+ * - utm_* → utm
929
+ * - r_<key> → referral (affiliate params)
930
+ * - ~<key> → deep_link_data (Branch-style)
931
+ * - click_id → click token
932
+ * - $deep_link_path / dlp → explicit in-app route override
933
+ */
934
+ declare function parseUniversalLink(url: string): SuperLinkDeepLink | null;
935
+
936
+ /**
937
+ * SuperLink — deferred deep linking / smart links public surface.
938
+ *
939
+ * Platform-agnostic + web entry points. React Native deferred attribution
940
+ * lives in `src/react-native/superlink.ts` and is exported from
941
+ * `sitepong/react-native` so non-RN bundles never pull in native deps.
942
+ */
943
+
944
+ /**
945
+ * Configure the SuperLink client. Safe to call on any platform.
946
+ *
947
+ * On web, this also captures any inbound deep-link params from the current
948
+ * URL immediately, so getDeepLink() is populated on first read.
949
+ *
950
+ * @example
951
+ * ```ts
952
+ * import { initSuperLink, getDeepLink } from 'sitepong';
953
+ * initSuperLink({ endpoint: 'https://go.acme.com', appId: 'abc' });
954
+ * const link = getDeepLink();
955
+ * ```
956
+ */
957
+ declare function initSuperLink(config?: SuperLinkConfig): void;
958
+
635
959
  interface SitePongConfig {
636
960
  apiKey: string;
637
961
  endpoint?: string;
@@ -716,6 +1040,10 @@ interface SitePongInitConfig extends SitePongConfig {
716
1040
  webVitals?: boolean;
717
1041
  navigationTiming?: boolean;
718
1042
  resourceTiming?: boolean;
1043
+ capturePageLoadTimings?: boolean;
1044
+ capturePageRenderTimings?: boolean;
1045
+ excludedResourceUrls?: string[];
1046
+ resourceNameSanitizer?: (url: string) => string;
719
1047
  sampleRate?: number;
720
1048
  flushInterval?: number;
721
1049
  performanceEndpoint?: string;
@@ -988,4 +1316,4 @@ declare const isRemoteConfigFeatureEnabled: (key: string, defaultValue?: boolean
988
1316
  declare const onRemoteConfigChange: (listener: (config: RemoteConfig) => void) => () => void;
989
1317
  declare const registerIdentifyHook: (hook: (userId: string) => void) => () => void;
990
1318
 
991
- export { type CapturedError, type CronCheckinOptions, type CronHandle, type DatabaseQueryEvent, type DatabaseTrackerConfig, type DeviceInfo, type DeviceSignals, type EnvironmentAdapter, type ErrorContext, type FraudCheckResult, GroupTraits, type MetricOptions, type MutableRNEnvironmentAdapter, type PerformanceConfig, type PerformanceSpan, type PerformanceTransaction, type PlatformName, type ProfileData, type ProfileFrame, type ProfilerConfig, type RemoteConfig, type RemoteConfigFeatures, type RemoteConfigSampling, ReplayConfig, type SitePongConfig, type SitePongInitConfig, type TraceContext, TracePropagator, TrackProperties, UserTraits, type VisitorIdResult, type WebManagerFactories, type WebVitals, addBreadcrumb, areFlagsReady, captureError, captureMessage, clearAnonymousId, clearUser, sitepong as client, createTraceContext, cronCheckin, cronStart, cronWrap, dbTrack, dbTrackSync, sitepong as default, endSpan, endTransaction, extractTrace, flush, flushMetrics, flushProfiles, generateSpanId, generateTraceId, getAllFlags, getAnonymousId, getDbNPlusOnePatterns, getDbQueryCount, getDeviceSignals, getFlag, getFraudCheck, getLatestProfile, getProfiles, getRemoteConfig, getReplaySessionId, getVariant, 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 };
1319
+ export { type CapturedError, type CronCheckinOptions, type CronHandle, DEFAULT_SUPERLINK_ENDPOINT, type DatabaseQueryEvent, type DatabaseTrackerConfig, type DeferredDeepLinkHandler, type DeviceInfo, type DeviceSignals, type EnvironmentAdapter, type ErrorContext, type FraudCheckResult, GroupTraits, type MetricOptions, type MutableRNEnvironmentAdapter, type PerformanceConfig, type PerformanceSpan, type PerformanceTransaction, type PlatformName, type ProfileData, type ProfileFrame, type ProfilerConfig, type RemoteConfig, type RemoteConfigFeatures, type RemoteConfigSampling, ReplayConfig, type ResourceTimingBreakdown, type SitePongConfig, type SitePongInitConfig, SuperLinkClient, type SuperLinkConfig, type SuperLinkDeepLink, type SuperLinkEventType, type SuperLinkFingerprint, type SuperLinkIdentityMetadata, type SuperLinkMatchRequest, type SuperLinkMatchResponse, type SuperLinkMatchType, type SuperLinkPlatform, type TraceContext, TracePropagator, TrackProperties, UserTraits, type VisitorIdResult, type WebManagerFactories, type WebVitals, addBreadcrumb, areFlagsReady, captureError, captureMessage, captureWebDeepLink, clearAnonymousId, clearUser, sitepong as client, completeFromScan, createTraceContext, cronCheckin, cronStart, cronWrap, dbTrack, dbTrackSync, sitepong 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, getVariantPayload, getVisitorId, getWebVitals, group, 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$1 as superlinkIdentify, track, trackPageView, waitForFlags, writeClipboardToken };