@neowhale/storefront 0.2.27 → 0.2.29
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/{chunk-PXS2DPVL.js → chunk-MZO7BCGU.js} +8 -4
- package/dist/chunk-MZO7BCGU.js.map +1 -0
- package/dist/{chunk-7KXJLHGA.cjs → chunk-UW2U5BRY.cjs} +8 -4
- package/dist/chunk-UW2U5BRY.cjs.map +1 -0
- package/dist/{chunk-VAA2KKCH.cjs → chunk-V5KCIYKG.cjs} +2 -2
- package/dist/chunk-V5KCIYKG.cjs.map +1 -0
- package/dist/{chunk-3Q7CPJBA.js → chunk-WNZOA4FB.js} +2 -2
- package/dist/chunk-WNZOA4FB.js.map +1 -0
- package/dist/{client-BSO263Uv.d.cts → client-CwCSPAHp.d.cts} +13 -1
- package/dist/{client-BSO263Uv.d.ts → client-CwCSPAHp.d.ts} +13 -1
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/next/index.cjs +4 -4
- package/dist/next/index.d.cts +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +1 -1
- package/dist/{pixel-manager-BcL95odX.d.ts → pixel-manager-LiLpBmPy.d.ts} +1 -1
- package/dist/{pixel-manager-DJ9m2FaQ.d.cts → pixel-manager-ti1xc1eC.d.cts} +1 -1
- package/dist/react/index.cjs +70 -21
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +10 -4
- package/dist/react/index.d.ts +10 -4
- package/dist/react/index.js +65 -16
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-3Q7CPJBA.js.map +0 -1
- package/dist/chunk-7KXJLHGA.cjs.map +0 -1
- package/dist/chunk-PXS2DPVL.js.map +0 -1
- package/dist/chunk-VAA2KKCH.cjs.map +0 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkUW2U5BRY_cjs = require('../chunk-UW2U5BRY.cjs');
|
|
4
|
+
var chunkV5KCIYKG_cjs = require('../chunk-V5KCIYKG.cjs');
|
|
5
5
|
var react = require('react');
|
|
6
6
|
var navigation = require('next/navigation');
|
|
7
7
|
var vanilla = require('zustand/vanilla');
|
|
@@ -499,6 +499,44 @@ function useAnalytics() {
|
|
|
499
499
|
},
|
|
500
500
|
[track]
|
|
501
501
|
);
|
|
502
|
+
const captureGeolocation = react.useCallback(
|
|
503
|
+
async (options) => {
|
|
504
|
+
if (!trackingEnabled) return null;
|
|
505
|
+
if (typeof navigator === "undefined" || !navigator.geolocation) return null;
|
|
506
|
+
try {
|
|
507
|
+
const position = await new Promise((resolve, reject) => {
|
|
508
|
+
navigator.geolocation.getCurrentPosition(resolve, reject, {
|
|
509
|
+
timeout: options?.timeout ?? 1e4,
|
|
510
|
+
enableHighAccuracy: options?.enableHighAccuracy ?? true
|
|
511
|
+
});
|
|
512
|
+
});
|
|
513
|
+
const { latitude, longitude, accuracy } = position.coords;
|
|
514
|
+
const sessionId = await getOrCreateSession();
|
|
515
|
+
if (sessionId && !sessionId.startsWith("local-")) {
|
|
516
|
+
await client.updateSession(sessionId, {
|
|
517
|
+
latitude,
|
|
518
|
+
longitude,
|
|
519
|
+
geolocation_source: "browser_gps",
|
|
520
|
+
geolocation_accuracy: accuracy
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
track("location_granted", {
|
|
524
|
+
accuracy,
|
|
525
|
+
trigger: "sdk",
|
|
526
|
+
device_type: detectDevice()
|
|
527
|
+
});
|
|
528
|
+
return position;
|
|
529
|
+
} catch (error) {
|
|
530
|
+
track("location_denied", {
|
|
531
|
+
error: error instanceof Error ? error.message : "unknown",
|
|
532
|
+
trigger: "sdk",
|
|
533
|
+
device_type: detectDevice()
|
|
534
|
+
});
|
|
535
|
+
return null;
|
|
536
|
+
}
|
|
537
|
+
},
|
|
538
|
+
[client, getOrCreateSession, track, trackingEnabled]
|
|
539
|
+
);
|
|
502
540
|
return {
|
|
503
541
|
track,
|
|
504
542
|
trackPageView,
|
|
@@ -513,6 +551,7 @@ function useAnalytics() {
|
|
|
513
551
|
updateSessionCart,
|
|
514
552
|
updateSessionOrder,
|
|
515
553
|
getOrCreateSession,
|
|
554
|
+
captureGeolocation,
|
|
516
555
|
/** Whether tracking is globally enabled for this storefront */
|
|
517
556
|
trackingEnabled,
|
|
518
557
|
/** Configured recording sample rate (0–1) for behavioral session replays */
|
|
@@ -635,7 +674,7 @@ function PixelInitializer({ onReady, onTheme }) {
|
|
|
635
674
|
onTheme(config.theme);
|
|
636
675
|
}
|
|
637
676
|
if (ctx.config.trackingEnabled && config.pixels && config.pixels.length > 0) {
|
|
638
|
-
const manager = new
|
|
677
|
+
const manager = new chunkUW2U5BRY_cjs.PixelManager(config.pixels);
|
|
639
678
|
await manager.initialize();
|
|
640
679
|
onReady(manager);
|
|
641
680
|
}
|
|
@@ -1027,7 +1066,7 @@ function BehavioralTrackerComponent({ pathname }) {
|
|
|
1027
1066
|
const baseUrl = config.proxyPath;
|
|
1028
1067
|
const endpoint = `${baseUrl}/v1/stores/${config.storeId}/storefront/behavioral`;
|
|
1029
1068
|
const sendBatch = async (batch) => {
|
|
1030
|
-
await
|
|
1069
|
+
await chunkV5KCIYKG_cjs.resilientSend(endpoint, batch, {
|
|
1031
1070
|
"Content-Type": "application/json",
|
|
1032
1071
|
"x-api-key": config.apiKey
|
|
1033
1072
|
});
|
|
@@ -1213,7 +1252,7 @@ function FingerprintCollector() {
|
|
|
1213
1252
|
collectFingerprint().then(async (fp) => {
|
|
1214
1253
|
const baseUrl = config.proxyPath;
|
|
1215
1254
|
const url = `${baseUrl}/v1/stores/${config.storeId}/storefront/fingerprints`;
|
|
1216
|
-
await
|
|
1255
|
+
await chunkV5KCIYKG_cjs.resilientSend(url, fp, {
|
|
1217
1256
|
"Content-Type": "application/json",
|
|
1218
1257
|
"x-api-key": config.apiKey
|
|
1219
1258
|
}).catch(() => {
|
|
@@ -1594,7 +1633,7 @@ function SessionRecorderComponent() {
|
|
|
1594
1633
|
const sid = sessionId;
|
|
1595
1634
|
const recorder = new SessionRecorder({
|
|
1596
1635
|
sendChunk: async (events, sequence) => {
|
|
1597
|
-
await
|
|
1636
|
+
await chunkV5KCIYKG_cjs.resilientSend(url, {
|
|
1598
1637
|
session_id: sid,
|
|
1599
1638
|
visitor_id: visitorId,
|
|
1600
1639
|
events,
|
|
@@ -1673,7 +1712,7 @@ function WhaleProvider({
|
|
|
1673
1712
|
trackingEnabled: trackingEnabled ?? envBool("NEXT_PUBLIC_TRACKING_ENABLED") ?? true,
|
|
1674
1713
|
recordingRate: recordingRate ?? envNumber("NEXT_PUBLIC_RECORDING_RATE") ?? 0.1
|
|
1675
1714
|
};
|
|
1676
|
-
const client = new
|
|
1715
|
+
const client = new chunkV5KCIYKG_cjs.WhaleClient({
|
|
1677
1716
|
storeId,
|
|
1678
1717
|
apiKey,
|
|
1679
1718
|
gatewayUrl: resolvedConfig.gatewayUrl,
|
|
@@ -2429,13 +2468,14 @@ function SectionRenderer({
|
|
|
2429
2468
|
section,
|
|
2430
2469
|
data,
|
|
2431
2470
|
theme,
|
|
2432
|
-
tracking
|
|
2471
|
+
tracking,
|
|
2472
|
+
onEvent
|
|
2433
2473
|
}) {
|
|
2434
2474
|
const [showCOA, setShowCOA] = react.useState(false);
|
|
2435
2475
|
const el = (() => {
|
|
2436
2476
|
switch (section.type) {
|
|
2437
2477
|
case "hero":
|
|
2438
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HeroSection, { section, theme, tracking });
|
|
2478
|
+
return /* @__PURE__ */ jsxRuntime.jsx(HeroSection, { section, theme, tracking, onEvent });
|
|
2439
2479
|
case "text":
|
|
2440
2480
|
return /* @__PURE__ */ jsxRuntime.jsx(TextSection, { section, theme });
|
|
2441
2481
|
case "image":
|
|
@@ -2445,7 +2485,7 @@ function SectionRenderer({
|
|
|
2445
2485
|
case "gallery":
|
|
2446
2486
|
return /* @__PURE__ */ jsxRuntime.jsx(GallerySection, { section, theme });
|
|
2447
2487
|
case "cta":
|
|
2448
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CTASection, { section, theme, tracking });
|
|
2488
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CTASection, { section, theme, tracking, onEvent });
|
|
2449
2489
|
case "stats":
|
|
2450
2490
|
return /* @__PURE__ */ jsxRuntime.jsx(StatsSection, { section, theme });
|
|
2451
2491
|
case "product_card":
|
|
@@ -2455,7 +2495,7 @@ function SectionRenderer({
|
|
|
2455
2495
|
case "social_links":
|
|
2456
2496
|
return /* @__PURE__ */ jsxRuntime.jsx(SocialLinksSection, { section, theme });
|
|
2457
2497
|
case "lead_capture":
|
|
2458
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LeadCaptureSection, { section, data, theme });
|
|
2498
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LeadCaptureSection, { section, data, theme, onEvent });
|
|
2459
2499
|
case "divider":
|
|
2460
2500
|
return /* @__PURE__ */ jsxRuntime.jsx(DividerSection, { theme });
|
|
2461
2501
|
default:
|
|
@@ -2467,7 +2507,7 @@ function SectionRenderer({
|
|
|
2467
2507
|
showCOA && data?.coa && /* @__PURE__ */ jsxRuntime.jsx(COAModal, { coa: data.coa, theme, onClose: () => setShowCOA(false) })
|
|
2468
2508
|
] });
|
|
2469
2509
|
}
|
|
2470
|
-
function HeroSection({ section, theme, tracking }) {
|
|
2510
|
+
function HeroSection({ section, theme, tracking, onEvent }) {
|
|
2471
2511
|
const { title, subtitle, background_image, cta_text, cta_url } = section.content;
|
|
2472
2512
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2473
2513
|
"div",
|
|
@@ -2509,7 +2549,10 @@ function HeroSection({ section, theme, tracking }) {
|
|
|
2509
2549
|
"a",
|
|
2510
2550
|
{
|
|
2511
2551
|
href: cta_url,
|
|
2512
|
-
onClick: () =>
|
|
2552
|
+
onClick: () => {
|
|
2553
|
+
trackClick(tracking, cta_text, cta_url);
|
|
2554
|
+
onEvent?.("cta_click", { label: cta_text, url: cta_url });
|
|
2555
|
+
},
|
|
2513
2556
|
style: {
|
|
2514
2557
|
display: "inline-block",
|
|
2515
2558
|
padding: "0.875rem 2rem",
|
|
@@ -2595,7 +2638,7 @@ function GallerySection({ section, theme }) {
|
|
|
2595
2638
|
}
|
|
2596
2639
|
) }, i)) }) });
|
|
2597
2640
|
}
|
|
2598
|
-
function CTASection({ section, theme, tracking }) {
|
|
2641
|
+
function CTASection({ section, theme, tracking, onEvent }) {
|
|
2599
2642
|
const { title, subtitle, buttons } = section.content;
|
|
2600
2643
|
if (!buttons || buttons.length === 0) return null;
|
|
2601
2644
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "2rem 1.5rem", maxWidth: 480, margin: "0 auto", display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
@@ -2624,7 +2667,10 @@ function CTASection({ section, theme, tracking }) {
|
|
|
2624
2667
|
"a",
|
|
2625
2668
|
{
|
|
2626
2669
|
href: btn.url,
|
|
2627
|
-
onClick: () =>
|
|
2670
|
+
onClick: () => {
|
|
2671
|
+
trackClick(tracking, btn.text, btn.url, i);
|
|
2672
|
+
onEvent?.("cta_click", { label: btn.text, url: btn.url });
|
|
2673
|
+
},
|
|
2628
2674
|
style: {
|
|
2629
2675
|
display: "block",
|
|
2630
2676
|
width: "100%",
|
|
@@ -2779,7 +2825,7 @@ function COAViewerSection({
|
|
|
2779
2825
|
onShowCOA();
|
|
2780
2826
|
}, style: buttonStyle, children: buttonLabel }) });
|
|
2781
2827
|
}
|
|
2782
|
-
function LeadCaptureSection({ section, data, theme }) {
|
|
2828
|
+
function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
2783
2829
|
const c = section.content;
|
|
2784
2830
|
const [firstName, setFirstName] = react.useState("");
|
|
2785
2831
|
const [email, setEmail] = react.useState("");
|
|
@@ -2816,6 +2862,7 @@ function LeadCaptureSection({ section, data, theme }) {
|
|
|
2816
2862
|
throw new Error(body?.error?.message || "Something went wrong. Please try again.");
|
|
2817
2863
|
}
|
|
2818
2864
|
setStatus("success");
|
|
2865
|
+
onEvent?.("lead", { email, first_name: firstName || void 0, source: c.source || "landing_page", landing_page_slug: slug || void 0 });
|
|
2819
2866
|
} catch (err) {
|
|
2820
2867
|
setErrorMsg(err instanceof Error ? err.message : "Something went wrong. Please try again.");
|
|
2821
2868
|
setStatus("error");
|
|
@@ -3352,7 +3399,8 @@ function LandingPage({
|
|
|
3352
3399
|
gatewayUrl = "https://whale-gateway.fly.dev",
|
|
3353
3400
|
renderSection,
|
|
3354
3401
|
onDataLoaded,
|
|
3355
|
-
onError
|
|
3402
|
+
onError,
|
|
3403
|
+
onEvent
|
|
3356
3404
|
}) {
|
|
3357
3405
|
const [state, setState] = react.useState("loading");
|
|
3358
3406
|
const [data, setData] = react.useState(null);
|
|
@@ -3400,12 +3448,13 @@ function LandingPage({
|
|
|
3400
3448
|
if (state === "expired") return /* @__PURE__ */ jsxRuntime.jsx(DefaultExpired2, {});
|
|
3401
3449
|
if (state === "error") return /* @__PURE__ */ jsxRuntime.jsx(DefaultError2, { message: errorMsg });
|
|
3402
3450
|
if (!data) return null;
|
|
3403
|
-
return /* @__PURE__ */ jsxRuntime.jsx(PageLayout, { data, gatewayUrl, renderSection });
|
|
3451
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PageLayout, { data, gatewayUrl, renderSection, onEvent });
|
|
3404
3452
|
}
|
|
3405
3453
|
function PageLayout({
|
|
3406
3454
|
data,
|
|
3407
3455
|
gatewayUrl,
|
|
3408
|
-
renderSection
|
|
3456
|
+
renderSection,
|
|
3457
|
+
onEvent
|
|
3409
3458
|
}) {
|
|
3410
3459
|
const { landing_page: lp, store } = data;
|
|
3411
3460
|
const theme = {
|
|
@@ -3425,11 +3474,11 @@ function PageLayout({
|
|
|
3425
3474
|
lp.custom_css && /* @__PURE__ */ jsxRuntime.jsx("style", { children: lp.custom_css }),
|
|
3426
3475
|
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" } }) }),
|
|
3427
3476
|
sorted.map((section) => {
|
|
3428
|
-
const defaultRenderer = () => /* @__PURE__ */ jsxRuntime.jsx(SectionRenderer, { section, data: sectionData, theme }, section.id);
|
|
3477
|
+
const defaultRenderer = () => /* @__PURE__ */ jsxRuntime.jsx(SectionRenderer, { section, data: sectionData, theme, onEvent }, section.id);
|
|
3429
3478
|
if (renderSection) {
|
|
3430
3479
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: renderSection(section, defaultRenderer) }, section.id);
|
|
3431
3480
|
}
|
|
3432
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SectionRenderer, { section, data: sectionData, theme }, section.id);
|
|
3481
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SectionRenderer, { section, data: sectionData, theme, onEvent }, section.id);
|
|
3433
3482
|
}),
|
|
3434
3483
|
store?.name && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "2rem 1.5rem", borderTop: `1px solid ${theme.surface}`, textAlign: "center" }, children: /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.75rem", color: theme.muted, margin: 0 }, children: [
|
|
3435
3484
|
"Powered by ",
|