@tagadapay/plugin-sdk 2.7.20 → 2.7.22
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/react/components/DebugDrawer.js +80 -2
- package/dist/react/hooks/useFunnel.d.ts +87 -3
- package/dist/react/hooks/useFunnel.js +77 -5
- package/dist/react/providers/TagadaProvider.d.ts +8 -0
- package/dist/react/providers/TagadaProvider.js +19 -0
- package/dist/v2/core/resources/funnel.d.ts +71 -5
- package/dist/v2/core/resources/funnel.js +27 -3
- package/dist/v2/index.d.ts +3 -2
- package/dist/v2/index.js +2 -1
- package/dist/v2/react/components/DebugDrawer.js +229 -15
- package/dist/v2/react/hooks/useFunnel.d.ts +4 -4
- package/dist/v2/react/hooks/useFunnel.js +37 -5
- package/dist/v2/react/hooks/usePostPurchasesQuery.js +129 -43
- package/dist/v2/react/index.d.ts +1 -0
- package/dist/v2/react/index.js +2 -0
- package/dist/v2/react/providers/TagadaProvider.d.ts +8 -0
- package/dist/v2/react/providers/TagadaProvider.js +94 -55
- package/package.json +1 -1
|
@@ -95,13 +95,32 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
|
|
|
95
95
|
{ id: 'session', label: 'Session' },
|
|
96
96
|
{ id: 'auth', label: 'Auth' },
|
|
97
97
|
];
|
|
98
|
+
// Add funnel tab if funnel is active
|
|
99
|
+
const funnelTab = context.debugFunnel.isActive ? [{ id: 'funnel', label: 'Funnel' }] : [];
|
|
100
|
+
// Debug: Log comprehensive debug drawer state
|
|
101
|
+
if (isOpen) {
|
|
102
|
+
console.group('🐛 [DebugDrawer] Comprehensive State Check');
|
|
103
|
+
console.log('1️⃣ Debug Mode:', context.debugMode);
|
|
104
|
+
console.log('2️⃣ Funnel Debug State:', {
|
|
105
|
+
isActive: context.debugFunnel.isActive,
|
|
106
|
+
hasData: !!context.debugFunnel.data,
|
|
107
|
+
hasError: !!context.debugFunnel.error,
|
|
108
|
+
isLoading: context.debugFunnel.isLoading,
|
|
109
|
+
lastUpdated: context.debugFunnel.lastUpdated,
|
|
110
|
+
});
|
|
111
|
+
console.log('3️⃣ Funnel Data (if any):', context.debugFunnel.data);
|
|
112
|
+
console.log('4️⃣ Funnel Error (if any):', context.debugFunnel.error);
|
|
113
|
+
console.log('5️⃣ Update Function Available:', typeof context.updateFunnelDebugData);
|
|
114
|
+
console.log('6️⃣ Will show Funnel tab:', funnelTab.length > 0);
|
|
115
|
+
console.groupEnd();
|
|
116
|
+
}
|
|
98
117
|
// Add checkout tab if checkout is active
|
|
99
118
|
const checkoutTab = context.debugCheckout.isActive ? [{ id: 'checkout', label: 'Checkout' }] : [];
|
|
100
119
|
// Add items tab if checkout has summary data
|
|
101
120
|
const itemsTab = context.debugCheckout.isActive && context.debugCheckout.data?.checkout?.summary
|
|
102
121
|
? [{ id: 'items', label: 'Items' }]
|
|
103
122
|
: [];
|
|
104
|
-
const tabs = [...baseTabs, ...checkoutTab, ...itemsTab, { id: 'raw', label: 'Raw Data' }];
|
|
123
|
+
const tabs = [...baseTabs, ...funnelTab, ...checkoutTab, ...itemsTab, { id: 'raw', label: 'Raw Data' }];
|
|
105
124
|
return (_jsxs(_Fragment, { children: [_jsx("div", { style: {
|
|
106
125
|
position: 'fixed',
|
|
107
126
|
top: 0,
|
|
@@ -169,7 +188,66 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
|
|
|
169
188
|
border: '1px solid #374151',
|
|
170
189
|
borderRadius: '6px',
|
|
171
190
|
marginTop: '16px',
|
|
172
|
-
}, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#f59e0b', fontSize: '14px' }, children: "Development Mode" }), _jsxs("p", { style: { margin: '0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Configuration is loaded from ", _jsx("code", { style: { color: '#60a5fa' }, children: "/.local.json" }), " and", ' ', _jsxs("code", { style: { color: '#60a5fa' }, children: ["/config/", pluginConfig.config?.configName || 'default', ".tgd.json"] })] }), _jsxs("p", { style: { margin: '8px 0 0 0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Local config variant:", ' ', _jsx("code", { style: { color: '#f59e0b' }, children: pluginConfig.config?.configName || 'default' })] })] }))] })), activeTab === 'store' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Store Configuration" }), context.store ? (_jsx(TreeView, { data: context.store, name: "store" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No store data available" }))] })), activeTab === 'session' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Session Data" }), context.session ? (_jsx(TreeView, { data: context.session, name: "session" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No session data available" }))] })), activeTab === 'auth' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Authentication State" }), _jsx(TreeView, { data: context.auth, name: "auth" }), context.customer && (_jsxs(_Fragment, { children: [_jsx("h4", { style: { margin: '24px 0 12px 0', color: '#60a5fa' }, children: "Customer Data" }), _jsx(TreeView, { data: context.customer, name: "customer" })] }))] })), activeTab === '
|
|
191
|
+
}, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#f59e0b', fontSize: '14px' }, children: "Development Mode" }), _jsxs("p", { style: { margin: '0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Configuration is loaded from ", _jsx("code", { style: { color: '#60a5fa' }, children: "/.local.json" }), " and", ' ', _jsxs("code", { style: { color: '#60a5fa' }, children: ["/config/", pluginConfig.config?.configName || 'default', ".tgd.json"] })] }), _jsxs("p", { style: { margin: '8px 0 0 0', fontSize: '12px', color: '#9ca3af', lineHeight: '1.4' }, children: ["Local config variant:", ' ', _jsx("code", { style: { color: '#f59e0b' }, children: pluginConfig.config?.configName || 'default' })] })] }))] })), activeTab === 'store' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Store Configuration" }), context.store ? (_jsx(TreeView, { data: context.store, name: "store" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No store data available" }))] })), activeTab === 'session' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Session Data" }), context.session ? (_jsx(TreeView, { data: context.session, name: "session" })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No session data available" }))] })), activeTab === 'auth' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Authentication State" }), _jsx(TreeView, { data: context.auth, name: "auth" }), context.customer && (_jsxs(_Fragment, { children: [_jsx("h4", { style: { margin: '24px 0 12px 0', color: '#60a5fa' }, children: "Customer Data" }), _jsx(TreeView, { data: context.customer, name: "customer" })] }))] })), activeTab === 'funnel' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Funnel Navigation" }), context.debugFunnel.isActive && context.debugFunnel.data ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Current Funnel" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Funnel Name:" }), _jsx("span", { style: { color: '#10b981', fontWeight: 'bold' }, children: context.debugFunnel.data.funnel?.name || 'Unknown' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Funnel ID:" }), _jsx("span", { style: { color: '#60a5fa', fontSize: '12px' }, children: context.debugFunnel.data.funnel?.id || 'N/A' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Total Steps:" }), _jsx("span", { style: { color: '#f59e0b' }, children: context.debugFunnel.data.funnel?.steps?.length || 0 })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Visited Steps:" }), _jsx("span", { style: { color: '#8b5cf6' }, children: context.debugFunnel.data.session?.totalStepsVisited || 0 })] }), context.debugFunnel.data.session?.cycleDetected && (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Cycle Detected:" }), _jsx("span", { style: { color: '#ef4444', fontWeight: 'bold' }, children: "\u26A0\uFE0F Yes" })] }))] })] }), context.debugFunnel.data.funnel?.steps && (_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsxs("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: ["Funnel Steps (", context.debugFunnel.data.funnel.steps.length, ")"] }), _jsx("div", { style: { display: 'grid', gap: '12px' }, children: context.debugFunnel.data.funnel.steps.map((step, index) => {
|
|
192
|
+
// Get current step ID from debug funnel data
|
|
193
|
+
const currentStepId = context.debugFunnel.data.session?.currentStepId;
|
|
194
|
+
// Determine if this is the current step
|
|
195
|
+
const isCurrent = step.id === currentStepId;
|
|
196
|
+
// Determine if this step was visited
|
|
197
|
+
const wasVisited = context.debugFunnel.data.session?.visitedSteps?.includes(step.id);
|
|
198
|
+
return (_jsxs("div", { style: {
|
|
199
|
+
border: isCurrent ? '2px solid #10b981' : '1px solid #374151',
|
|
200
|
+
borderRadius: '8px',
|
|
201
|
+
padding: '12px',
|
|
202
|
+
backgroundColor: isCurrent ? '#064e3b' : '#111827',
|
|
203
|
+
position: 'relative',
|
|
204
|
+
}, children: [isCurrent && (_jsx("div", { style: {
|
|
205
|
+
position: 'absolute',
|
|
206
|
+
top: '8px',
|
|
207
|
+
right: '8px',
|
|
208
|
+
backgroundColor: '#10b981',
|
|
209
|
+
color: '#000',
|
|
210
|
+
padding: '2px 8px',
|
|
211
|
+
borderRadius: '4px',
|
|
212
|
+
fontSize: '10px',
|
|
213
|
+
fontWeight: 'bold',
|
|
214
|
+
}, children: "CURRENT" })), wasVisited && !isCurrent && (_jsx("div", { style: {
|
|
215
|
+
position: 'absolute',
|
|
216
|
+
top: '8px',
|
|
217
|
+
right: '8px',
|
|
218
|
+
backgroundColor: '#8b5cf6',
|
|
219
|
+
color: '#fff',
|
|
220
|
+
padding: '2px 8px',
|
|
221
|
+
borderRadius: '4px',
|
|
222
|
+
fontSize: '10px',
|
|
223
|
+
fontWeight: 'bold',
|
|
224
|
+
}, children: "VISITED" })), _jsxs("div", { style: {
|
|
225
|
+
marginBottom: '8px',
|
|
226
|
+
marginRight: wasVisited || isCurrent ? '80px' : '0',
|
|
227
|
+
}, children: [_jsxs("div", { style: {
|
|
228
|
+
color: isCurrent ? '#6ee7b7' : '#f9fafb',
|
|
229
|
+
fontWeight: 'bold',
|
|
230
|
+
marginBottom: '4px',
|
|
231
|
+
fontSize: '14px',
|
|
232
|
+
}, children: [step.name || `Step ${index + 1}`, step.isEntry && (_jsx("span", { style: {
|
|
233
|
+
marginLeft: '8px',
|
|
234
|
+
fontSize: '10px',
|
|
235
|
+
backgroundColor: '#3b82f6',
|
|
236
|
+
color: '#fff',
|
|
237
|
+
padding: '2px 6px',
|
|
238
|
+
borderRadius: '4px',
|
|
239
|
+
}, children: "ENTRY" }))] }), _jsxs("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: ["Type: ", step.type, " \u2022 Index: ", step.index, step.row !== undefined && ` • Row: ${step.row}`] }), step.url && (_jsxs("div", { style: { fontSize: '11px', color: '#60a5fa', marginTop: '4px' }, children: ["URL: ", step.url] }))] }), step.conditions && (_jsxs("div", { style: {
|
|
240
|
+
backgroundColor: '#1f2937',
|
|
241
|
+
padding: '8px',
|
|
242
|
+
borderRadius: '4px',
|
|
243
|
+
marginTop: '8px',
|
|
244
|
+
}, children: [_jsx("div", { style: {
|
|
245
|
+
fontSize: '10px',
|
|
246
|
+
color: '#60a5fa',
|
|
247
|
+
fontWeight: 'bold',
|
|
248
|
+
marginBottom: '4px',
|
|
249
|
+
}, children: "Conditions:" }), _jsx(TreeView, { data: step.conditions, name: "conditions", maxLevel: 2 })] })), _jsxs("div", { style: { fontSize: '9px', color: '#6b7280', marginTop: '8px' }, children: ["ID: ", step.id] })] }, step.id || index));
|
|
250
|
+
}) })] })), _jsxs("div", { children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Full Funnel Data" }), _jsx(TreeView, { data: context.debugFunnel.data, name: "funnelDebugData", maxLevel: 3 })] })] })) : (_jsxs("p", { style: { color: '#6b7280' }, children: ["No funnel data available. Use the ", _jsx("code", { children: "useFunnel" }), " hook to activate funnel tracking."] }))] })), activeTab === 'items' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Items & Discounts" }), context.debugCheckout.data?.checkout?.summary ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Summary" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Currency:" }), _jsx("span", { style: { color: '#f59e0b' }, children: context.debugCheckout.data.checkout.summary.currency })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Subtotal:" }), _jsx("span", { style: { color: '#9ca3af' }, children: (() => {
|
|
173
251
|
try {
|
|
174
252
|
return context.money.formatMoney(Number(context.debugCheckout.data.checkout.summary.subtotalAmount) || 0, String(context.debugCheckout.data.checkout.summary.currency) || 'USD', context.locale.locale);
|
|
175
253
|
}
|
|
@@ -1,8 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Funnel event types enum
|
|
3
|
+
*
|
|
4
|
+
* Special types:
|
|
5
|
+
* - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
|
|
6
|
+
* - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
|
|
7
|
+
*
|
|
8
|
+
* Common types (for logging/tracking):
|
|
9
|
+
* - Any string value is accepted, but these are commonly used examples
|
|
10
|
+
*/
|
|
11
|
+
export declare enum FunnelEventType {
|
|
12
|
+
DIRECT_NAVIGATION = "direct_navigation",
|
|
13
|
+
BACK_NAVIGATION = "back_navigation",
|
|
14
|
+
PAYMENT_SUCCESS = "payment_success",
|
|
15
|
+
CUSTOM = "custom"
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Data structures for specific event types
|
|
19
|
+
*/
|
|
20
|
+
export type NextEvent<T> = T & {
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
};
|
|
23
|
+
export interface DirectNavigationEventData {
|
|
24
|
+
targetStepId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface BackNavigationEventData {
|
|
27
|
+
targetStepId: string;
|
|
28
|
+
}
|
|
29
|
+
export interface QuizCompletedEventData {
|
|
30
|
+
quiz: {
|
|
31
|
+
score: number;
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface OfferAcceptedEventData {
|
|
36
|
+
offer: {
|
|
37
|
+
accepted: boolean;
|
|
38
|
+
offerId?: string;
|
|
39
|
+
[key: string]: any;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export interface FormSubmitEventData {
|
|
43
|
+
[key: string]: any;
|
|
44
|
+
}
|
|
45
|
+
export interface PaymentSuccessEventData {
|
|
46
|
+
payment?: {
|
|
47
|
+
status: 'success';
|
|
48
|
+
amount: number;
|
|
49
|
+
currency: string;
|
|
50
|
+
orderId?: string;
|
|
51
|
+
transactionId?: string;
|
|
52
|
+
timestamp?: string;
|
|
53
|
+
[key: string]: any;
|
|
54
|
+
};
|
|
55
|
+
order?: {
|
|
56
|
+
id: string;
|
|
57
|
+
amount: number;
|
|
58
|
+
currency: string;
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
};
|
|
61
|
+
paymentId?: string;
|
|
62
|
+
[key: string]: any;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Base properties shared by all FunnelEvent types
|
|
66
|
+
*/
|
|
67
|
+
interface BaseFunnelEvent {
|
|
68
|
+
/**
|
|
69
|
+
* Event timestamp
|
|
70
|
+
*/
|
|
4
71
|
timestamp?: Date;
|
|
5
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Discriminated union for FunnelEvent based on event type
|
|
75
|
+
*/
|
|
76
|
+
export type FunnelEvent = BaseFunnelEvent & (({
|
|
77
|
+
type: FunnelEventType.DIRECT_NAVIGATION;
|
|
78
|
+
data: NextEvent<DirectNavigationEventData>;
|
|
79
|
+
}) | ({
|
|
80
|
+
type: FunnelEventType.BACK_NAVIGATION;
|
|
81
|
+
data: NextEvent<BackNavigationEventData>;
|
|
82
|
+
}) | ({
|
|
83
|
+
type: FunnelEventType.PAYMENT_SUCCESS;
|
|
84
|
+
data?: NextEvent<PaymentSuccessEventData>;
|
|
85
|
+
}) | ({
|
|
86
|
+
type: FunnelEventType.CUSTOM;
|
|
87
|
+
data?: NextEvent<any>;
|
|
88
|
+
}));
|
|
6
89
|
export interface FunnelNavigationAction {
|
|
7
90
|
type: 'redirect' | 'replace' | 'push' | 'external' | 'none';
|
|
8
91
|
url?: string;
|
|
@@ -68,3 +151,4 @@ export declare function useSimpleFunnel(funnelId: string, initialStepId?: string
|
|
|
68
151
|
goToStep: (stepId: string) => Promise<any>;
|
|
69
152
|
isLoading: boolean;
|
|
70
153
|
};
|
|
154
|
+
export {};
|
|
@@ -1,5 +1,23 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { useTagadaContext } from '../providers/TagadaProvider';
|
|
3
|
+
/**
|
|
4
|
+
* Funnel event types enum
|
|
5
|
+
*
|
|
6
|
+
* Special types:
|
|
7
|
+
* - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
|
|
8
|
+
* - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
|
|
9
|
+
*
|
|
10
|
+
* Common types (for logging/tracking):
|
|
11
|
+
* - Any string value is accepted, but these are commonly used examples
|
|
12
|
+
*/
|
|
13
|
+
export var FunnelEventType;
|
|
14
|
+
(function (FunnelEventType) {
|
|
15
|
+
// Special navigation types
|
|
16
|
+
FunnelEventType["DIRECT_NAVIGATION"] = "direct_navigation";
|
|
17
|
+
FunnelEventType["BACK_NAVIGATION"] = "back_navigation";
|
|
18
|
+
FunnelEventType["PAYMENT_SUCCESS"] = "payment_success";
|
|
19
|
+
FunnelEventType["CUSTOM"] = "custom";
|
|
20
|
+
})(FunnelEventType || (FunnelEventType = {}));
|
|
3
21
|
/**
|
|
4
22
|
* React Hook for Funnel Navigation (Plugin SDK Version)
|
|
5
23
|
*
|
|
@@ -7,7 +25,7 @@ import { useTagadaContext } from '../providers/TagadaProvider';
|
|
|
7
25
|
* Integrates with TagadaPay authentication and plugin routing.
|
|
8
26
|
*/
|
|
9
27
|
export function useFunnel(options) {
|
|
10
|
-
const { auth, apiService, store } = useTagadaContext();
|
|
28
|
+
const { auth, apiService, store, updateFunnelDebugData, debugMode } = useTagadaContext();
|
|
11
29
|
const [isLoading, setIsLoading] = useState(false);
|
|
12
30
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
13
31
|
const [context, setContext] = useState(null);
|
|
@@ -19,6 +37,35 @@ export function useFunnel(options) {
|
|
|
19
37
|
const urlFunnelId = urlParams.get('funnelId') || undefined;
|
|
20
38
|
const effectiveFunnelId = urlFunnelId || options.funnelId;
|
|
21
39
|
// Removed checkExistingSession - now handled in single initialize call
|
|
40
|
+
/**
|
|
41
|
+
* Fetch funnel session with debug data (debug mode only)
|
|
42
|
+
*/
|
|
43
|
+
const fetchFunnelDebugData = useCallback(async (sessionId) => {
|
|
44
|
+
if (!debugMode) {
|
|
45
|
+
console.log('🐛 [useFunnel] Debug mode is OFF, skipping debug data fetch');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log('🐛 [useFunnel] Fetching debug data for session:', sessionId);
|
|
49
|
+
try {
|
|
50
|
+
const response = await apiService.fetch(`/api/v1/funnel/session/${sessionId}`, {
|
|
51
|
+
method: 'GET',
|
|
52
|
+
params: {
|
|
53
|
+
includeDebugData: 'true',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
console.log('🐛 [useFunnel] Debug data response:', response);
|
|
57
|
+
if (response.success && response.debugData) {
|
|
58
|
+
updateFunnelDebugData(response.debugData, null, false);
|
|
59
|
+
console.log('🐛 [useFunnel] Debug data updated successfully:', response.debugData);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.warn('🐛 [useFunnel] No debug data in response');
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('🐛 [useFunnel] Failed to fetch funnel debug data:', error);
|
|
67
|
+
}
|
|
68
|
+
}, [apiService, debugMode, updateFunnelDebugData]);
|
|
22
69
|
/**
|
|
23
70
|
* Set funnel session cookie
|
|
24
71
|
*/
|
|
@@ -91,6 +138,19 @@ export function useFunnel(options) {
|
|
|
91
138
|
// Set session cookie for persistence across page reloads
|
|
92
139
|
setSessionCookie(response.context.sessionId);
|
|
93
140
|
console.log(`🍪 Funnel: Initialized new session for funnel ${effectiveFunnelId || 'default'}`, response.context);
|
|
141
|
+
// Fetch debug data if in debug mode
|
|
142
|
+
console.log('🐛 [useFunnel INIT] Checking debug mode:', {
|
|
143
|
+
debugMode,
|
|
144
|
+
sessionId: response.context.sessionId,
|
|
145
|
+
hasUpdateFunction: typeof updateFunnelDebugData,
|
|
146
|
+
});
|
|
147
|
+
if (debugMode) {
|
|
148
|
+
console.log('🐛 [useFunnel INIT] Debug mode is ON, calling fetchFunnelDebugData...');
|
|
149
|
+
void fetchFunnelDebugData(response.context.sessionId);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.warn('🐛 [useFunnel INIT] Debug mode is OFF, will not fetch debug data');
|
|
153
|
+
}
|
|
94
154
|
}
|
|
95
155
|
else {
|
|
96
156
|
throw new Error(response.error || 'Failed to initialize funnel session');
|
|
@@ -108,7 +168,7 @@ export function useFunnel(options) {
|
|
|
108
168
|
finally {
|
|
109
169
|
setIsLoading(false);
|
|
110
170
|
}
|
|
111
|
-
}, [auth.session?.customerId, store?.id, effectiveFunnelId, apiService, options.onError]);
|
|
171
|
+
}, [auth.session?.customerId, store?.id, effectiveFunnelId, apiService, options.onError, debugMode, fetchFunnelDebugData]);
|
|
112
172
|
/**
|
|
113
173
|
* Navigate to next step based on event
|
|
114
174
|
*/
|
|
@@ -177,6 +237,18 @@ export function useFunnel(options) {
|
|
|
177
237
|
performNavigation(updatedAction);
|
|
178
238
|
}
|
|
179
239
|
console.log(`🍪 Funnel: Navigated from ${context.currentStepId} to ${result.stepId}`);
|
|
240
|
+
// Fetch debug data if in debug mode
|
|
241
|
+
console.log('🐛 [useFunnel NAV] After navigation, checking debug mode:', {
|
|
242
|
+
debugMode,
|
|
243
|
+
sessionId: newContext.sessionId,
|
|
244
|
+
});
|
|
245
|
+
if (debugMode && newContext.sessionId) {
|
|
246
|
+
console.log('🐛 [useFunnel NAV] Fetching debug data after navigation...');
|
|
247
|
+
void fetchFunnelDebugData(newContext.sessionId);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
console.warn('🐛 [useFunnel NAV] Not fetching debug data:', { debugMode, hasSessionId: !!newContext.sessionId });
|
|
251
|
+
}
|
|
180
252
|
return result;
|
|
181
253
|
}
|
|
182
254
|
else {
|
|
@@ -193,13 +265,13 @@ export function useFunnel(options) {
|
|
|
193
265
|
finally {
|
|
194
266
|
setIsLoading(false);
|
|
195
267
|
}
|
|
196
|
-
}, [context, apiService, options.onNavigate, options.onError]);
|
|
268
|
+
}, [context, apiService, options.onNavigate, options.onError, debugMode, fetchFunnelDebugData]);
|
|
197
269
|
/**
|
|
198
270
|
* Go directly to a specific step (bypass conditions)
|
|
199
271
|
*/
|
|
200
272
|
const goToStep = useCallback(async (stepId) => {
|
|
201
273
|
return next({
|
|
202
|
-
type:
|
|
274
|
+
type: FunnelEventType.DIRECT_NAVIGATION,
|
|
203
275
|
data: { targetStepId: stepId },
|
|
204
276
|
timestamp: new Date()
|
|
205
277
|
});
|
|
@@ -29,6 +29,14 @@ interface TagadaContextValue {
|
|
|
29
29
|
lastUpdated: Date | null;
|
|
30
30
|
};
|
|
31
31
|
updateCheckoutDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
|
|
32
|
+
debugFunnel: {
|
|
33
|
+
isActive: boolean;
|
|
34
|
+
data: any;
|
|
35
|
+
error: Error | null;
|
|
36
|
+
isLoading: boolean;
|
|
37
|
+
lastUpdated: Date | null;
|
|
38
|
+
};
|
|
39
|
+
updateFunnelDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
|
|
32
40
|
refreshCoordinator: {
|
|
33
41
|
registerCheckoutRefresh: (refreshFn: () => Promise<void>) => void;
|
|
34
42
|
registerOrderBumpRefresh: (refreshFn: () => Promise<void>) => void;
|
|
@@ -198,6 +198,14 @@ rawPluginConfig, }) {
|
|
|
198
198
|
isLoading: false,
|
|
199
199
|
lastUpdated: null,
|
|
200
200
|
});
|
|
201
|
+
// Initialize debug funnel state
|
|
202
|
+
const [debugFunnel, setDebugFunnel] = useState({
|
|
203
|
+
isActive: false,
|
|
204
|
+
data: null,
|
|
205
|
+
error: null,
|
|
206
|
+
isLoading: false,
|
|
207
|
+
lastUpdated: null,
|
|
208
|
+
});
|
|
201
209
|
// Initialize auth state
|
|
202
210
|
const [auth, setAuth] = useState({
|
|
203
211
|
isAuthenticated: false,
|
|
@@ -518,6 +526,16 @@ rawPluginConfig, }) {
|
|
|
518
526
|
lastUpdated: new Date(),
|
|
519
527
|
});
|
|
520
528
|
},
|
|
529
|
+
debugFunnel,
|
|
530
|
+
updateFunnelDebugData: (data, error, isLoading) => {
|
|
531
|
+
setDebugFunnel({
|
|
532
|
+
isActive: true,
|
|
533
|
+
data,
|
|
534
|
+
error: error ?? null,
|
|
535
|
+
isLoading: isLoading ?? false,
|
|
536
|
+
lastUpdated: new Date(),
|
|
537
|
+
});
|
|
538
|
+
},
|
|
521
539
|
refreshCoordinator,
|
|
522
540
|
money: {
|
|
523
541
|
formatMoney,
|
|
@@ -544,6 +562,7 @@ rawPluginConfig, }) {
|
|
|
544
562
|
pluginConfig,
|
|
545
563
|
configLoading,
|
|
546
564
|
debugCheckout,
|
|
565
|
+
debugFunnel,
|
|
547
566
|
refreshCoordinator,
|
|
548
567
|
]);
|
|
549
568
|
// Determine if we should show loading
|
|
@@ -2,9 +2,57 @@
|
|
|
2
2
|
* Funnel Resource - API client for funnel navigation and session management
|
|
3
3
|
*/
|
|
4
4
|
import { ApiClient } from './apiClient';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Funnel event types enum
|
|
7
|
+
*
|
|
8
|
+
* Special types:
|
|
9
|
+
* - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
|
|
10
|
+
* - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
|
|
11
|
+
*
|
|
12
|
+
* Common types (for logging/tracking):
|
|
13
|
+
* - Any string value is accepted, but these are commonly used examples
|
|
14
|
+
*/
|
|
15
|
+
export declare enum FunnelEventType {
|
|
16
|
+
DIRECT_NAVIGATION = "direct_navigation",
|
|
17
|
+
BACK_NAVIGATION = "back_navigation",
|
|
18
|
+
PAYMENT_SUCCESS = "payment_success",
|
|
19
|
+
CUSTOM = "custom"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Data structures for specific event types
|
|
23
|
+
*/
|
|
24
|
+
export type NextEvent<T> = T & {
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
};
|
|
27
|
+
export interface DirectNavigationEventData {
|
|
28
|
+
targetStepId: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BackNavigationEventData {
|
|
31
|
+
targetStepId: string;
|
|
32
|
+
}
|
|
33
|
+
export interface PaymentSuccessEventData {
|
|
34
|
+
payment: {
|
|
35
|
+
id: string;
|
|
36
|
+
status: string;
|
|
37
|
+
transactionId?: string;
|
|
38
|
+
timestamp?: string;
|
|
39
|
+
[key: string]: any;
|
|
40
|
+
};
|
|
41
|
+
order: {
|
|
42
|
+
id: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
currency: string;
|
|
45
|
+
[key: string]: any;
|
|
46
|
+
};
|
|
47
|
+
[key: string]: any;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Base properties shared by all FunnelEvent types
|
|
51
|
+
*/
|
|
52
|
+
interface BaseFunnelEvent {
|
|
53
|
+
/**
|
|
54
|
+
* Event timestamp (ISO string format)
|
|
55
|
+
*/
|
|
8
56
|
timestamp?: string;
|
|
9
57
|
/**
|
|
10
58
|
* Current URL for session synchronization (browser back/forward handling)
|
|
@@ -13,6 +61,22 @@ export interface FunnelEvent {
|
|
|
13
61
|
*/
|
|
14
62
|
currentUrl?: string;
|
|
15
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Discriminated union for FunnelEvent based on event type
|
|
66
|
+
*/
|
|
67
|
+
export type FunnelAction = BaseFunnelEvent & (({
|
|
68
|
+
type: FunnelEventType.DIRECT_NAVIGATION;
|
|
69
|
+
data: NextEvent<DirectNavigationEventData>;
|
|
70
|
+
}) | ({
|
|
71
|
+
type: FunnelEventType.BACK_NAVIGATION;
|
|
72
|
+
data: NextEvent<BackNavigationEventData>;
|
|
73
|
+
}) | ({
|
|
74
|
+
type: FunnelEventType.PAYMENT_SUCCESS;
|
|
75
|
+
data: NextEvent<PaymentSuccessEventData>;
|
|
76
|
+
}) | ({
|
|
77
|
+
type: FunnelEventType.CUSTOM;
|
|
78
|
+
data?: NextEvent<any>;
|
|
79
|
+
}));
|
|
16
80
|
export interface FunnelNavigationAction {
|
|
17
81
|
type: 'redirect' | 'replace' | 'push' | 'external' | 'none';
|
|
18
82
|
url?: string;
|
|
@@ -63,7 +127,7 @@ export interface FunnelInitializeResponse {
|
|
|
63
127
|
}
|
|
64
128
|
export interface FunnelNavigateRequest {
|
|
65
129
|
sessionId: string;
|
|
66
|
-
event:
|
|
130
|
+
event: FunnelAction;
|
|
67
131
|
contextUpdates?: Partial<SimpleFunnelContext>;
|
|
68
132
|
/**
|
|
69
133
|
* Current URL for URL-to-Step mapping (browser back/forward sync)
|
|
@@ -129,9 +193,11 @@ export declare class FunnelResource {
|
|
|
129
193
|
* @param sessionId - The session ID to fetch
|
|
130
194
|
* @param currentUrl - Optional current URL for session synchronization on page load
|
|
131
195
|
*/
|
|
132
|
-
getSession(sessionId: string, currentUrl?: string): Promise<{
|
|
196
|
+
getSession(sessionId: string, currentUrl?: string, includeDebugData?: boolean): Promise<{
|
|
133
197
|
success: boolean;
|
|
134
198
|
context?: SimpleFunnelContext;
|
|
199
|
+
debugData?: any;
|
|
135
200
|
error?: string;
|
|
136
201
|
}>;
|
|
137
202
|
}
|
|
203
|
+
export {};
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Funnel Resource - API client for funnel navigation and session management
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Funnel event types enum
|
|
6
|
+
*
|
|
7
|
+
* Special types:
|
|
8
|
+
* - DIRECT_NAVIGATION: Bypasses step conditions, navigates directly to targetStepId
|
|
9
|
+
* - BACK_NAVIGATION: Similar to direct_navigation, used for backward navigation
|
|
10
|
+
*
|
|
11
|
+
* Common types (for logging/tracking):
|
|
12
|
+
* - Any string value is accepted, but these are commonly used examples
|
|
13
|
+
*/
|
|
14
|
+
export var FunnelEventType;
|
|
15
|
+
(function (FunnelEventType) {
|
|
16
|
+
// Special navigation types
|
|
17
|
+
FunnelEventType["DIRECT_NAVIGATION"] = "direct_navigation";
|
|
18
|
+
FunnelEventType["BACK_NAVIGATION"] = "back_navigation";
|
|
19
|
+
FunnelEventType["PAYMENT_SUCCESS"] = "payment_success";
|
|
20
|
+
FunnelEventType["CUSTOM"] = "custom";
|
|
21
|
+
})(FunnelEventType || (FunnelEventType = {}));
|
|
4
22
|
export class FunnelResource {
|
|
5
23
|
constructor(apiClient) {
|
|
6
24
|
this.apiClient = apiClient;
|
|
@@ -34,9 +52,15 @@ export class FunnelResource {
|
|
|
34
52
|
* @param sessionId - The session ID to fetch
|
|
35
53
|
* @param currentUrl - Optional current URL for session synchronization on page load
|
|
36
54
|
*/
|
|
37
|
-
async getSession(sessionId, currentUrl) {
|
|
38
|
-
const params =
|
|
39
|
-
|
|
55
|
+
async getSession(sessionId, currentUrl, includeDebugData) {
|
|
56
|
+
const params = new URLSearchParams();
|
|
57
|
+
if (currentUrl) {
|
|
58
|
+
params.append('currentUrl', currentUrl);
|
|
59
|
+
}
|
|
60
|
+
if (includeDebugData) {
|
|
61
|
+
params.append('includeDebugData', 'true');
|
|
62
|
+
}
|
|
63
|
+
const url = `/api/v1/funnel/session/${sessionId}${params.toString() ? `?${params}` : ''}`;
|
|
40
64
|
return this.apiClient.get(url);
|
|
41
65
|
}
|
|
42
66
|
}
|
package/dist/v2/index.d.ts
CHANGED
|
@@ -21,8 +21,9 @@ export type { ShippingRate, ShippingRatesResponse } from './core/resources/shipp
|
|
|
21
21
|
export type { ApplyDiscountResponse, Discount, DiscountCodeValidation, RemoveDiscountResponse } from './core/resources/discounts';
|
|
22
22
|
export type { ToggleOrderBumpResponse, VipOffer, VipPreviewResponse } from './core/resources/vipOffers';
|
|
23
23
|
export type { StoreConfig } from './core/resources/storeConfig';
|
|
24
|
-
export
|
|
25
|
-
export {
|
|
24
|
+
export { FunnelEventType } from './core/resources/funnel';
|
|
25
|
+
export type { BackNavigationEventData, DirectNavigationEventData, FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelAction as FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, NextEvent, PaymentSuccessEventData, SimpleFunnelContext } from './core/resources/funnel';
|
|
26
|
+
export { ApplePayButton, ExpressPaymentMethodsProvider, GooglePayButton, TagadaProvider, formatMoney, getAvailableLanguages, queryKeys, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useISOData, useInvalidateQuery, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|
|
26
27
|
export type { TranslateFunction, TranslationText, UseTranslationOptions, UseTranslationResult } from './react/hooks/useTranslation';
|
|
27
28
|
export type { ClubOffer, ClubOfferItem, ClubOfferLineItem, ClubOfferSummary, UseClubOffersOptions, UseClubOffersResult } from './react/hooks/useClubOffers';
|
|
28
29
|
export type { UseLoginOptions, UseLoginResult } from './react/hooks/useLogin';
|
package/dist/v2/index.js
CHANGED
|
@@ -13,5 +13,6 @@ export * from './core/utils/pluginConfig';
|
|
|
13
13
|
export * from './core/utils/products';
|
|
14
14
|
// Path remapping helpers (framework-agnostic)
|
|
15
15
|
export * from './core/pathRemapping';
|
|
16
|
+
export { FunnelEventType } from './core/resources/funnel';
|
|
16
17
|
// React exports (hooks and components only, types are exported above)
|
|
17
|
-
export { ApplePayButton, ExpressPaymentMethodsProvider,
|
|
18
|
+
export { ApplePayButton, ExpressPaymentMethodsProvider, GooglePayButton, TagadaProvider, formatMoney, getAvailableLanguages, queryKeys, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useGeoLocation, useGoogleAutocomplete, useISOData, useInvalidateQuery, useLanguageImport, useLogin, useOffers, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|