@neowhale/storefront 0.2.30 → 0.2.32

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.
@@ -1,4 +1,4 @@
1
- import { F as WhaleStorefrontConfig, W as WhaleClient, r as Product } from '../client-CwCSPAHp.cjs';
1
+ import { F as WhaleStorefrontConfig, W as WhaleClient, r as Product } from '../client-CUKv5fMM.cjs';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { F as WhaleStorefrontConfig, W as WhaleClient, r as Product } from '../client-CwCSPAHp.js';
1
+ import { F as WhaleStorefrontConfig, W as WhaleClient, r as Product } from '../client-CUKv5fMM.js';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { WhaleClient } from '../chunk-WNZOA4FB.js';
1
+ import { WhaleClient } from '../chunk-2XODSXJT.js';
2
2
  import { NextResponse } from 'next/server';
3
3
 
4
4
  // src/next/headers.ts
@@ -1,4 +1,4 @@
1
- import { p as PixelConfig } from './client-CwCSPAHp.js';
1
+ import { p as PixelConfig } from './client-CUKv5fMM.js';
2
2
 
3
3
  declare class PixelManager {
4
4
  private providers;
@@ -1,4 +1,4 @@
1
- import { p as PixelConfig } from './client-CwCSPAHp.cjs';
1
+ import { p as PixelConfig } from './client-CUKv5fMM.cjs';
2
2
 
3
3
  declare class PixelManager {
4
4
  private providers;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkUW2U5BRY_cjs = require('../chunk-UW2U5BRY.cjs');
4
- var chunkV5KCIYKG_cjs = require('../chunk-V5KCIYKG.cjs');
4
+ var chunkHSGM4XMK_cjs = require('../chunk-HSGM4XMK.cjs');
5
5
  var react = require('react');
6
6
  var navigation = require('next/navigation');
7
7
  var vanilla = require('zustand/vanilla');
@@ -555,7 +555,9 @@ function useAnalytics() {
555
555
  /** Whether tracking is globally enabled for this storefront */
556
556
  trackingEnabled,
557
557
  /** Configured recording sample rate (0–1) for behavioral session replays */
558
- recordingRate: config.recordingRate
558
+ recordingRate: config.recordingRate,
559
+ /** Stable visitor ID for cross-session attribution */
560
+ visitorId: getVisitorId(config.storagePrefix)
559
561
  };
560
562
  }
561
563
  function useAuth() {
@@ -1066,7 +1068,7 @@ function BehavioralTrackerComponent({ pathname }) {
1066
1068
  const baseUrl = config.proxyPath;
1067
1069
  const endpoint = `${baseUrl}/v1/stores/${config.storeId}/storefront/behavioral`;
1068
1070
  const sendBatch = async (batch) => {
1069
- await chunkV5KCIYKG_cjs.resilientSend(endpoint, batch, {
1071
+ await chunkHSGM4XMK_cjs.resilientSend(endpoint, batch, {
1070
1072
  "Content-Type": "application/json",
1071
1073
  "x-api-key": config.apiKey
1072
1074
  });
@@ -1252,7 +1254,7 @@ function FingerprintCollector() {
1252
1254
  collectFingerprint().then(async (fp) => {
1253
1255
  const baseUrl = config.proxyPath;
1254
1256
  const url = `${baseUrl}/v1/stores/${config.storeId}/storefront/fingerprints`;
1255
- await chunkV5KCIYKG_cjs.resilientSend(url, fp, {
1257
+ await chunkHSGM4XMK_cjs.resilientSend(url, fp, {
1256
1258
  "Content-Type": "application/json",
1257
1259
  "x-api-key": config.apiKey
1258
1260
  }).catch(() => {
@@ -1633,7 +1635,7 @@ function SessionRecorderComponent() {
1633
1635
  const sid = sessionId;
1634
1636
  const recorder = new SessionRecorder({
1635
1637
  sendChunk: async (events, sequence) => {
1636
- await chunkV5KCIYKG_cjs.resilientSend(url, {
1638
+ await chunkHSGM4XMK_cjs.resilientSend(url, {
1637
1639
  session_id: sid,
1638
1640
  visitor_id: visitorId,
1639
1641
  events,
@@ -1712,7 +1714,7 @@ function WhaleProvider({
1712
1714
  trackingEnabled: trackingEnabled ?? envBool("NEXT_PUBLIC_TRACKING_ENABLED") ?? true,
1713
1715
  recordingRate: recordingRate ?? envNumber("NEXT_PUBLIC_RECORDING_RATE") ?? 0.1
1714
1716
  };
1715
- const client = new chunkV5KCIYKG_cjs.WhaleClient({
1717
+ const client = new chunkHSGM4XMK_cjs.WhaleClient({
1716
1718
  storeId,
1717
1719
  apiKey,
1718
1720
  gatewayUrl: resolvedConfig.gatewayUrl,
@@ -1866,6 +1868,7 @@ function useCustomerAnalytics() {
1866
1868
  function useCheckout() {
1867
1869
  const ctx = react.useContext(WhaleContext);
1868
1870
  if (!ctx) throw new Error("useCheckout must be used within <WhaleProvider>");
1871
+ const { visitorId, getOrCreateSession: getAnalyticsSession } = useAnalytics();
1869
1872
  const [session, setSession] = react.useState(null);
1870
1873
  const [loading, setLoading] = react.useState(false);
1871
1874
  const [error, setError] = react.useState(null);
@@ -1873,7 +1876,12 @@ function useCheckout() {
1873
1876
  setLoading(true);
1874
1877
  setError(null);
1875
1878
  try {
1876
- const data = await ctx.client.createCheckoutSession(params);
1879
+ const analyticsSessionId = await getAnalyticsSession().catch(() => void 0);
1880
+ const data = await ctx.client.createCheckoutSession({
1881
+ ...params,
1882
+ visitor_id: visitorId,
1883
+ session_id: analyticsSessionId?.startsWith("local-") ? void 0 : analyticsSessionId
1884
+ });
1877
1885
  setSession(data);
1878
1886
  return data;
1879
1887
  } catch (err) {
@@ -2902,6 +2910,8 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2902
2910
  if (!email || !storeId) return;
2903
2911
  setStatus("loading");
2904
2912
  setErrorMsg("");
2913
+ const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
2914
+ const analyticsData = data.analyticsContext;
2905
2915
  try {
2906
2916
  const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
2907
2917
  method: "POST",
@@ -2916,7 +2926,13 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2916
2926
  const t = [...c.tags || []];
2917
2927
  if (newsletterOptIn) t.push(c.newsletter_tag || "newsletter-subscriber");
2918
2928
  return t.length > 0 ? t : void 0;
2919
- })()
2929
+ })(),
2930
+ visitor_id: analyticsData?.visitorId || void 0,
2931
+ session_id: analyticsData?.sessionId || void 0,
2932
+ utm_source: urlParams?.get("utm_source") || void 0,
2933
+ utm_medium: urlParams?.get("utm_medium") || void 0,
2934
+ utm_campaign: urlParams?.get("utm_campaign") || void 0,
2935
+ utm_content: urlParams?.get("utm_content") || void 0
2920
2936
  })
2921
2937
  });
2922
2938
  if (!res.ok) {
@@ -3462,7 +3478,8 @@ function LandingPage({
3462
3478
  renderSection,
3463
3479
  onDataLoaded,
3464
3480
  onError,
3465
- onEvent
3481
+ onEvent,
3482
+ analyticsContext
3466
3483
  }) {
3467
3484
  const [state, setState] = react.useState("loading");
3468
3485
  const [data, setData] = react.useState(null);
@@ -3510,13 +3527,14 @@ function LandingPage({
3510
3527
  if (state === "expired") return /* @__PURE__ */ jsxRuntime.jsx(DefaultExpired2, {});
3511
3528
  if (state === "error") return /* @__PURE__ */ jsxRuntime.jsx(DefaultError2, { message: errorMsg });
3512
3529
  if (!data) return null;
3513
- return /* @__PURE__ */ jsxRuntime.jsx(PageLayout, { data, gatewayUrl, renderSection, onEvent });
3530
+ return /* @__PURE__ */ jsxRuntime.jsx(PageLayout, { data, gatewayUrl, renderSection, onEvent, analyticsContext });
3514
3531
  }
3515
3532
  function PageLayout({
3516
3533
  data,
3517
3534
  gatewayUrl,
3518
3535
  renderSection,
3519
- onEvent
3536
+ onEvent,
3537
+ analyticsContext
3520
3538
  }) {
3521
3539
  const { landing_page: lp, store } = data;
3522
3540
  const theme = {
@@ -3531,7 +3549,7 @@ function PageLayout({
3531
3549
  const fontFamily = lp.font_family || theme.fontDisplay || "system-ui, -apple-system, sans-serif";
3532
3550
  const logoUrl = store?.logo_url;
3533
3551
  const sorted = [...lp.sections].sort((a, b) => a.order - b.order);
3534
- const sectionData = { ...data, gatewayUrl, landing_page: { slug: lp.slug } };
3552
+ const sectionData = { ...data, gatewayUrl, landing_page: { slug: lp.slug }, analyticsContext };
3535
3553
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minHeight: "100dvh", background: theme.bg, color: theme.fg, fontFamily }, children: [
3536
3554
  lp.custom_css && /* @__PURE__ */ jsxRuntime.jsx("style", { children: lp.custom_css }),
3537
3555
  logoUrl && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "1.5rem", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: store?.name || "Store", style: { height: 40, objectFit: "contain" } }) }),