@tagadapay/plugin-sdk 3.0.3 → 3.0.12
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/build-cdn.js +113 -0
- package/dist/config/basisTheory.d.ts +26 -0
- package/dist/config/basisTheory.js +29 -0
- package/dist/external-tracker.js +5072 -0
- package/dist/external-tracker.min.js +11 -0
- package/dist/external-tracker.min.js.map +7 -0
- package/dist/react/config/payment.d.ts +8 -8
- package/dist/react/config/payment.js +17 -21
- package/dist/react/hooks/useApplePay.js +1 -1
- package/dist/react/hooks/usePayment.js +1 -3
- package/dist/react/hooks/useThreeds.js +2 -2
- package/dist/v2/core/client.d.ts +30 -3
- package/dist/v2/core/client.js +326 -8
- package/dist/v2/core/config/environment.d.ts +16 -3
- package/dist/v2/core/config/environment.js +72 -3
- package/dist/v2/core/funnelClient.d.ts +4 -0
- package/dist/v2/core/funnelClient.js +106 -4
- package/dist/v2/core/resources/funnel.d.ts +22 -0
- package/dist/v2/core/resources/offers.d.ts +64 -3
- package/dist/v2/core/resources/offers.js +112 -10
- package/dist/v2/core/resources/postPurchases.js +4 -1
- package/dist/v2/core/utils/configHotReload.d.ts +39 -0
- package/dist/v2/core/utils/configHotReload.js +75 -0
- package/dist/v2/core/utils/eventBus.d.ts +11 -0
- package/dist/v2/core/utils/eventBus.js +34 -0
- package/dist/v2/core/utils/pluginConfig.d.ts +14 -5
- package/dist/v2/core/utils/pluginConfig.js +74 -59
- package/dist/v2/core/utils/previewMode.d.ts +114 -0
- package/dist/v2/core/utils/previewMode.js +379 -0
- package/dist/v2/core/utils/sessionStorage.d.ts +5 -0
- package/dist/v2/core/utils/sessionStorage.js +22 -0
- package/dist/v2/index.d.ts +4 -1
- package/dist/v2/index.js +3 -1
- package/dist/v2/react/components/DebugDrawer.js +68 -46
- package/dist/v2/react/hooks/useOfferQuery.js +50 -17
- package/dist/v2/react/hooks/usePaymentQuery.js +1 -3
- package/dist/v2/react/hooks/usePreviewOffer.d.ts +84 -0
- package/dist/v2/react/hooks/usePreviewOffer.js +290 -0
- package/dist/v2/react/hooks/useThreeds.js +2 -2
- package/dist/v2/react/index.d.ts +2 -0
- package/dist/v2/react/index.js +1 -0
- package/dist/v2/react/providers/TagadaProvider.js +49 -32
- package/dist/v2/standalone/external-tracker.d.ts +119 -0
- package/dist/v2/standalone/external-tracker.js +260 -0
- package/dist/v2/standalone/index.d.ts +2 -0
- package/dist/v2/standalone/index.js +6 -0
- package/package.json +11 -3
- package/dist/v2/react/hooks/useOffersQuery.d.ts +0 -12
- package/dist/v2/react/hooks/useOffersQuery.js +0 -404
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Override Parameters
|
|
3
|
+
*
|
|
4
|
+
* Centralized parameter management for SDK behavior overrides.
|
|
5
|
+
* Parameters can come from URL query params, localStorage, or cookies.
|
|
6
|
+
*
|
|
7
|
+
* Key concepts:
|
|
8
|
+
* - forceReset: Clears all stored state (localStorage, cookies) - simulates hard refresh
|
|
9
|
+
* - draft: Marks customers/sessions as draft (for staging/preview/testing)
|
|
10
|
+
* - funnelTracking: Controls whether funnel events are tracked
|
|
11
|
+
* - tagadaClientEnv: Forces specific environment (production/development/local) - overrides auto-detection
|
|
12
|
+
* - tagadaClientBaseUrl: Forces custom API base URL - overrides environment-based URL
|
|
13
|
+
* - token: Authentication token (URL > localStorage)
|
|
14
|
+
* - funnelSessionId: Active funnel session (URL > cookie)
|
|
15
|
+
*
|
|
16
|
+
* Usage examples:
|
|
17
|
+
* - Force production API: ?tagadaClientEnv=production
|
|
18
|
+
* - Force development API: ?tagadaClientEnv=development
|
|
19
|
+
* - Force local API: ?tagadaClientEnv=local
|
|
20
|
+
* - Custom API URL: ?tagadaClientBaseUrl=https://tagada.loclx.io
|
|
21
|
+
* - Combined: ?tagadaClientEnv=local&tagadaClientBaseUrl=https://tagada.loclx.io
|
|
22
|
+
* - Hard reset + production: ?forceReset=true&tagadaClientEnv=production
|
|
23
|
+
*/
|
|
24
|
+
import { clearClientToken, setClientToken, getClientToken } from './tokenStorage';
|
|
25
|
+
import { clearFunnelSessionCookie } from './sessionStorage';
|
|
26
|
+
// Storage keys for SDK override params
|
|
27
|
+
const STORAGE_KEYS = {
|
|
28
|
+
DRAFT: 'tgd_draft',
|
|
29
|
+
FUNNEL_TRACKING: 'tgd_funnel_tracking',
|
|
30
|
+
FORCE_RESET: 'tgd_force_reset',
|
|
31
|
+
CLIENT_ENV: 'tgd_client_env',
|
|
32
|
+
CLIENT_BASE_URL: 'tgd_client_base_url',
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Check if force reset is active (simulates hard refresh)
|
|
36
|
+
*/
|
|
37
|
+
export function isForceReset() {
|
|
38
|
+
if (typeof window === 'undefined')
|
|
39
|
+
return false;
|
|
40
|
+
const params = new URLSearchParams(window.location.search);
|
|
41
|
+
return params.get('forceReset') === 'true';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get value from localStorage with fallback
|
|
45
|
+
*/
|
|
46
|
+
function getFromStorage(key) {
|
|
47
|
+
if (typeof window === 'undefined')
|
|
48
|
+
return null;
|
|
49
|
+
try {
|
|
50
|
+
return localStorage.getItem(key);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Set value in localStorage
|
|
58
|
+
*/
|
|
59
|
+
function setInStorage(key, value) {
|
|
60
|
+
if (typeof window === 'undefined')
|
|
61
|
+
return;
|
|
62
|
+
try {
|
|
63
|
+
localStorage.setItem(key, value);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
// Storage not available
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Get value from cookie
|
|
71
|
+
*/
|
|
72
|
+
function getFromCookie(key) {
|
|
73
|
+
if (typeof document === 'undefined')
|
|
74
|
+
return null;
|
|
75
|
+
const cookies = document.cookie.split(';');
|
|
76
|
+
const cookie = cookies.find(c => c.trim().startsWith(`${key}=`));
|
|
77
|
+
return cookie ? cookie.split('=')[1]?.trim() : null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Set value in cookie
|
|
81
|
+
*/
|
|
82
|
+
function setInCookie(key, value, maxAge = 86400) {
|
|
83
|
+
if (typeof document === 'undefined')
|
|
84
|
+
return;
|
|
85
|
+
document.cookie = `${key}=${value}; path=/; max-age=${maxAge}`;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Clear value from cookie
|
|
89
|
+
*/
|
|
90
|
+
function clearFromCookie(key) {
|
|
91
|
+
if (typeof document === 'undefined')
|
|
92
|
+
return;
|
|
93
|
+
document.cookie = `${key}=; path=/; max-age=0`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get SDK override parameters from all sources (URL, localStorage, cookies)
|
|
97
|
+
* Priority: URL > localStorage > Cookie
|
|
98
|
+
*/
|
|
99
|
+
export function getSDKParams() {
|
|
100
|
+
if (typeof window === 'undefined') {
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
104
|
+
// Get draft mode (URL > localStorage > cookie)
|
|
105
|
+
let draft;
|
|
106
|
+
const urlDraft = urlParams.get('draft');
|
|
107
|
+
if (urlDraft !== null) {
|
|
108
|
+
draft = urlDraft === 'true';
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const storageDraft = getFromStorage(STORAGE_KEYS.DRAFT) || getFromCookie(STORAGE_KEYS.DRAFT);
|
|
112
|
+
if (storageDraft !== null) {
|
|
113
|
+
draft = storageDraft === 'true';
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Get funnel tracking (URL > localStorage > cookie, default true)
|
|
117
|
+
let funnelTracking;
|
|
118
|
+
const urlTracking = urlParams.get('funnelTracking');
|
|
119
|
+
if (urlTracking !== null) {
|
|
120
|
+
funnelTracking = urlTracking !== 'false';
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const storageTracking = getFromStorage(STORAGE_KEYS.FUNNEL_TRACKING) || getFromCookie(STORAGE_KEYS.FUNNEL_TRACKING);
|
|
124
|
+
if (storageTracking !== null) {
|
|
125
|
+
funnelTracking = storageTracking !== 'false';
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Get token (URL > localStorage)
|
|
129
|
+
const token = urlParams.get('token') || getClientToken() || null;
|
|
130
|
+
// Get funnel session ID (URL only, cookie handled elsewhere)
|
|
131
|
+
const funnelSessionId = urlParams.get('funnelSessionId') || null;
|
|
132
|
+
// Get funnel ID (URL only)
|
|
133
|
+
const funnelId = urlParams.get('funnelId') || null;
|
|
134
|
+
// Force reset is URL-only (not persisted)
|
|
135
|
+
const forceReset = urlParams.get('forceReset') === 'true';
|
|
136
|
+
// Get client environment override (URL > localStorage > cookie)
|
|
137
|
+
let tagadaClientEnv;
|
|
138
|
+
const urlEnv = urlParams.get('tagadaClientEnv');
|
|
139
|
+
if (urlEnv && (urlEnv === 'production' || urlEnv === 'development' || urlEnv === 'local')) {
|
|
140
|
+
tagadaClientEnv = urlEnv;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
const storageEnv = getFromStorage(STORAGE_KEYS.CLIENT_ENV) || getFromCookie(STORAGE_KEYS.CLIENT_ENV);
|
|
144
|
+
if (storageEnv && (storageEnv === 'production' || storageEnv === 'development' || storageEnv === 'local')) {
|
|
145
|
+
tagadaClientEnv = storageEnv;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Get custom API base URL override (URL > localStorage > cookie)
|
|
149
|
+
let tagadaClientBaseUrl;
|
|
150
|
+
const urlBaseUrl = urlParams.get('tagadaClientBaseUrl');
|
|
151
|
+
if (urlBaseUrl) {
|
|
152
|
+
tagadaClientBaseUrl = urlBaseUrl;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const storageBaseUrl = getFromStorage(STORAGE_KEYS.CLIENT_BASE_URL) || getFromCookie(STORAGE_KEYS.CLIENT_BASE_URL);
|
|
156
|
+
if (storageBaseUrl) {
|
|
157
|
+
tagadaClientBaseUrl = storageBaseUrl;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
forceReset,
|
|
162
|
+
token,
|
|
163
|
+
funnelSessionId,
|
|
164
|
+
funnelId,
|
|
165
|
+
draft,
|
|
166
|
+
funnelTracking,
|
|
167
|
+
tagadaClientEnv,
|
|
168
|
+
tagadaClientBaseUrl,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Legacy alias for backward compatibility
|
|
173
|
+
* @deprecated Use getSDKParams() instead
|
|
174
|
+
*/
|
|
175
|
+
export function getPreviewParams() {
|
|
176
|
+
return getSDKParams();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if draft mode is active
|
|
180
|
+
* Uses centralized getSDKParams()
|
|
181
|
+
*/
|
|
182
|
+
export function isDraftMode() {
|
|
183
|
+
const params = getSDKParams();
|
|
184
|
+
return params.draft ?? false;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Set draft mode in storage for persistence
|
|
188
|
+
*/
|
|
189
|
+
export function setDraftMode(draft) {
|
|
190
|
+
if (typeof window === 'undefined')
|
|
191
|
+
return;
|
|
192
|
+
if (draft) {
|
|
193
|
+
setInStorage(STORAGE_KEYS.DRAFT, 'true');
|
|
194
|
+
setInCookie(STORAGE_KEYS.DRAFT, 'true', 86400); // 24 hours
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
setInStorage(STORAGE_KEYS.DRAFT, 'false');
|
|
198
|
+
clearFromCookie(STORAGE_KEYS.DRAFT);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Initialize SDK with override parameters
|
|
203
|
+
*
|
|
204
|
+
* This function handles SDK initialization based on override params:
|
|
205
|
+
* 1. If forceReset flag is set: Clear all stored state (simulates hard refresh)
|
|
206
|
+
* 2. If token in URL: Use it (override localStorage)
|
|
207
|
+
* 3. If draft in URL: Persist it to storage
|
|
208
|
+
* 4. If funnelTracking in URL: Persist it to storage
|
|
209
|
+
*
|
|
210
|
+
* @returns True if force reset was activated and state was cleared
|
|
211
|
+
*/
|
|
212
|
+
export function handlePreviewMode(debugMode = false) {
|
|
213
|
+
const params = getSDKParams();
|
|
214
|
+
const shouldReset = params.forceReset || false;
|
|
215
|
+
if (!shouldReset && !params.token) {
|
|
216
|
+
// Not forcing reset and no explicit token override
|
|
217
|
+
// But still persist draft/tracking if in URL
|
|
218
|
+
persistSDKParamsFromURL();
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (debugMode) {
|
|
222
|
+
console.log('[SDK] Detected params:', params);
|
|
223
|
+
}
|
|
224
|
+
// CASE 1: Force reset - clear all state (simulates hard refresh)
|
|
225
|
+
if (shouldReset) {
|
|
226
|
+
if (debugMode) {
|
|
227
|
+
console.log('[SDK] Force reset: Clearing all stored state');
|
|
228
|
+
}
|
|
229
|
+
clearClientToken();
|
|
230
|
+
clearFunnelSessionCookie();
|
|
231
|
+
// Clear all tagadapay-related localStorage keys
|
|
232
|
+
if (typeof window !== 'undefined' && window.localStorage) {
|
|
233
|
+
const keys = Object.keys(localStorage);
|
|
234
|
+
keys.forEach(key => {
|
|
235
|
+
if (key.startsWith('tagadapay_') || key.startsWith('tgd_')) {
|
|
236
|
+
if (debugMode) {
|
|
237
|
+
console.log(`[SDK] Clearing localStorage: ${key}`);
|
|
238
|
+
}
|
|
239
|
+
localStorage.removeItem(key);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// CASE 2: Token in URL - override stored token
|
|
245
|
+
if (params.token !== null && params.token !== undefined) {
|
|
246
|
+
if (debugMode) {
|
|
247
|
+
console.log('[SDK] Using token from URL:', params.token.substring(0, 20) + '...');
|
|
248
|
+
}
|
|
249
|
+
if (params.token === '' || params.token === 'null') {
|
|
250
|
+
// Explicitly cleared token
|
|
251
|
+
clearClientToken();
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
// Set token from URL
|
|
255
|
+
setClientToken(params.token);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
else if (shouldReset) {
|
|
259
|
+
// Force reset but no token = clear stored token
|
|
260
|
+
if (debugMode) {
|
|
261
|
+
console.log('[SDK] Force reset mode (no token)');
|
|
262
|
+
}
|
|
263
|
+
clearClientToken();
|
|
264
|
+
}
|
|
265
|
+
// CASE 3: Persist URL params to storage
|
|
266
|
+
persistSDKParamsFromURL();
|
|
267
|
+
// CASE 4: Funnel session ID in URL - will be used by FunnelClient
|
|
268
|
+
if (params.funnelSessionId && debugMode) {
|
|
269
|
+
console.log('[SDK] Using funnelSessionId from URL:', params.funnelSessionId);
|
|
270
|
+
}
|
|
271
|
+
return shouldReset;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Persist SDK parameters from URL to storage
|
|
275
|
+
* This ensures params survive page navigation
|
|
276
|
+
*/
|
|
277
|
+
function persistSDKParamsFromURL() {
|
|
278
|
+
if (typeof window === 'undefined')
|
|
279
|
+
return;
|
|
280
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
281
|
+
// Persist draft mode if in URL
|
|
282
|
+
const urlDraft = urlParams.get('draft');
|
|
283
|
+
if (urlDraft !== null) {
|
|
284
|
+
setDraftMode(urlDraft === 'true');
|
|
285
|
+
}
|
|
286
|
+
// Persist funnel tracking if in URL
|
|
287
|
+
const urlTracking = urlParams.get('funnelTracking');
|
|
288
|
+
if (urlTracking !== null) {
|
|
289
|
+
setFunnelTracking(urlTracking !== 'false');
|
|
290
|
+
}
|
|
291
|
+
// Persist client environment if in URL
|
|
292
|
+
const urlEnv = urlParams.get('tagadaClientEnv');
|
|
293
|
+
if (urlEnv && (urlEnv === 'production' || urlEnv === 'development' || urlEnv === 'local')) {
|
|
294
|
+
setClientEnvironment(urlEnv);
|
|
295
|
+
}
|
|
296
|
+
// Persist custom base URL if in URL
|
|
297
|
+
const urlBaseUrl = urlParams.get('tagadaClientBaseUrl');
|
|
298
|
+
if (urlBaseUrl) {
|
|
299
|
+
setClientBaseUrl(urlBaseUrl);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Set funnel tracking mode in storage for persistence
|
|
304
|
+
*/
|
|
305
|
+
export function setFunnelTracking(enabled) {
|
|
306
|
+
if (typeof window === 'undefined')
|
|
307
|
+
return;
|
|
308
|
+
const value = enabled ? 'true' : 'false';
|
|
309
|
+
setInStorage(STORAGE_KEYS.FUNNEL_TRACKING, value);
|
|
310
|
+
setInCookie(STORAGE_KEYS.FUNNEL_TRACKING, value, 86400); // 24 hours
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Set client environment override in storage for persistence
|
|
314
|
+
*/
|
|
315
|
+
export function setClientEnvironment(env) {
|
|
316
|
+
if (typeof window === 'undefined')
|
|
317
|
+
return;
|
|
318
|
+
setInStorage(STORAGE_KEYS.CLIENT_ENV, env);
|
|
319
|
+
setInCookie(STORAGE_KEYS.CLIENT_ENV, env, 86400); // 24 hours
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Clear client environment override
|
|
323
|
+
*/
|
|
324
|
+
export function clearClientEnvironment() {
|
|
325
|
+
if (typeof window === 'undefined')
|
|
326
|
+
return;
|
|
327
|
+
try {
|
|
328
|
+
localStorage.removeItem(STORAGE_KEYS.CLIENT_ENV);
|
|
329
|
+
clearFromCookie(STORAGE_KEYS.CLIENT_ENV);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// Storage not available
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Set custom API base URL override in storage for persistence
|
|
337
|
+
*/
|
|
338
|
+
export function setClientBaseUrl(baseUrl) {
|
|
339
|
+
if (typeof window === 'undefined')
|
|
340
|
+
return;
|
|
341
|
+
setInStorage(STORAGE_KEYS.CLIENT_BASE_URL, baseUrl);
|
|
342
|
+
setInCookie(STORAGE_KEYS.CLIENT_BASE_URL, baseUrl, 86400); // 24 hours
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Clear custom API base URL override
|
|
346
|
+
*/
|
|
347
|
+
export function clearClientBaseUrl() {
|
|
348
|
+
if (typeof window === 'undefined')
|
|
349
|
+
return;
|
|
350
|
+
try {
|
|
351
|
+
localStorage.removeItem(STORAGE_KEYS.CLIENT_BASE_URL);
|
|
352
|
+
clearFromCookie(STORAGE_KEYS.CLIENT_BASE_URL);
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
// Storage not available
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Check if we should use URL params over stored values
|
|
360
|
+
*
|
|
361
|
+
* Returns true if:
|
|
362
|
+
* - Force reset is active, OR
|
|
363
|
+
* - Explicit token/sessionId in URL (indicating intentional override)
|
|
364
|
+
*/
|
|
365
|
+
export function shouldUseUrlParams() {
|
|
366
|
+
const params = getSDKParams();
|
|
367
|
+
return !!(params.forceReset ||
|
|
368
|
+
params.token !== null ||
|
|
369
|
+
params.funnelSessionId !== null);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Check if funnel tracking is enabled
|
|
373
|
+
* Uses centralized getSDKParams()
|
|
374
|
+
* Default is true for normal operations
|
|
375
|
+
*/
|
|
376
|
+
export function isFunnelTrackingEnabled() {
|
|
377
|
+
const params = getSDKParams();
|
|
378
|
+
return params.funnelTracking ?? true; // Default true
|
|
379
|
+
}
|
|
@@ -18,3 +18,8 @@ export declare function clearFunnelSessionCookie(): void;
|
|
|
18
18
|
* Check if a funnel session cookie exists
|
|
19
19
|
*/
|
|
20
20
|
export declare function hasFunnelSessionCookie(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Retrieve funnel variant ID from sticky session (for A/B tracking)
|
|
23
|
+
* The variant ID is stored in the sticky session metadata by plugin-routing
|
|
24
|
+
*/
|
|
25
|
+
export declare function getFunnelVariantId(): string | undefined;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Handles session persistence using browser cookies
|
|
4
4
|
*/
|
|
5
5
|
const FUNNEL_SESSION_COOKIE_NAME = 'tgd-funnel-session-id';
|
|
6
|
+
const STICKY_SESSION_COOKIE_NAME = 'tgd-session-id';
|
|
6
7
|
const SESSION_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
|
|
7
8
|
/**
|
|
8
9
|
* Save funnel session ID to browser cookie
|
|
@@ -37,3 +38,24 @@ export function clearFunnelSessionCookie() {
|
|
|
37
38
|
export function hasFunnelSessionCookie() {
|
|
38
39
|
return !!getFunnelSessionCookie();
|
|
39
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Retrieve funnel variant ID from sticky session (for A/B tracking)
|
|
43
|
+
* The variant ID is stored in the sticky session metadata by plugin-routing
|
|
44
|
+
*/
|
|
45
|
+
export function getFunnelVariantId() {
|
|
46
|
+
if (typeof document === 'undefined')
|
|
47
|
+
return undefined;
|
|
48
|
+
try {
|
|
49
|
+
const cookie = document.cookie
|
|
50
|
+
.split('; ')
|
|
51
|
+
.find((row) => row.startsWith(`${STICKY_SESSION_COOKIE_NAME}=`));
|
|
52
|
+
if (!cookie)
|
|
53
|
+
return undefined;
|
|
54
|
+
const sessionData = JSON.parse(decodeURIComponent(cookie.split('=')[1]));
|
|
55
|
+
return sessionData?.metadata?.funnelVariantId;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
console.warn('Failed to parse sticky session for variant ID:', error);
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/v2/index.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './core/isoData';
|
|
|
10
10
|
export * from './core/utils/currency';
|
|
11
11
|
export * from './core/utils/pluginConfig';
|
|
12
12
|
export * from './core/utils/products';
|
|
13
|
+
export * from './core/utils/previewMode';
|
|
14
|
+
export * from './core/utils/configHotReload';
|
|
13
15
|
export * from './core/pathRemapping';
|
|
14
16
|
export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutSessionPreview, Promotion } from './core/resources/checkout';
|
|
15
17
|
export type { Order, OrderLineItem } from './core/utils/order';
|
|
@@ -23,7 +25,7 @@ export type { ToggleOrderBumpResponse, VipOffer, VipPreviewResponse } from './co
|
|
|
23
25
|
export type { StoreConfig } from './core/resources/storeConfig';
|
|
24
26
|
export { FunnelActionType } from './core/resources/funnel';
|
|
25
27
|
export type { BackNavigationActionData, CartUpdatedActionData, DirectNavigationActionData, FormSubmitActionData, FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelAction as FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, NextAction, OfferAcceptedActionData, OfferDeclinedActionData, PaymentFailedActionData, PaymentSuccessActionData, SimpleFunnelContext } from './core/resources/funnel';
|
|
26
|
-
export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|
|
28
|
+
export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, usePreviewOffer, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|
|
27
29
|
export type { DebugScript } from './react';
|
|
28
30
|
export type { TranslateFunction, TranslationText, UseTranslationOptions, UseTranslationResult } from './react/hooks/useTranslation';
|
|
29
31
|
export type { FunnelContextValue } from './react/hooks/useFunnel';
|
|
@@ -36,3 +38,4 @@ export type { UseCustomerInfosOptions, UseCustomerInfosResult } from './react/ho
|
|
|
36
38
|
export type { UseCustomerOrdersOptions, UseCustomerOrdersResult } from './react/hooks/useCustomerOrders';
|
|
37
39
|
export type { UseCustomerSubscriptionsOptions, UseCustomerSubscriptionsResult } from './react/hooks/useCustomerSubscriptions';
|
|
38
40
|
export type { UseShippingRatesQueryOptions, UseShippingRatesQueryResult } from './react/hooks/useShippingRatesQuery';
|
|
41
|
+
export type { PreviewOfferSummary, UsePreviewOfferOptions, UsePreviewOfferResult } from './react/hooks/usePreviewOffer';
|
package/dist/v2/index.js
CHANGED
|
@@ -11,8 +11,10 @@ export * from './core/isoData';
|
|
|
11
11
|
export * from './core/utils/currency';
|
|
12
12
|
export * from './core/utils/pluginConfig';
|
|
13
13
|
export * from './core/utils/products';
|
|
14
|
+
export * from './core/utils/previewMode';
|
|
15
|
+
export * from './core/utils/configHotReload';
|
|
14
16
|
// Path remapping helpers (framework-agnostic)
|
|
15
17
|
export * from './core/pathRemapping';
|
|
16
18
|
export { FunnelActionType } from './core/resources/funnel';
|
|
17
19
|
// React exports (hooks and components only, types are exported above)
|
|
18
|
-
export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|
|
20
|
+
export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, usePreviewOffer, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
|
|
@@ -79,6 +79,7 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
|
|
|
79
79
|
const [activeTab, setActiveTab] = useState('overview');
|
|
80
80
|
const [runningScripts, setRunningScripts] = useState(new Set());
|
|
81
81
|
const [scriptResults, setScriptResults] = useState({});
|
|
82
|
+
const [expandedScriptCategories, setExpandedScriptCategories] = useState({});
|
|
82
83
|
// Handler to jump to a specific step using direct_navigation
|
|
83
84
|
const handleJumpToStep = async (stepId, stepName) => {
|
|
84
85
|
// Try to get sessionId from debug data or context
|
|
@@ -187,8 +188,9 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
|
|
|
187
188
|
const script = context.debugScripts?.find((s) => s.id === scriptId);
|
|
188
189
|
if (!script)
|
|
189
190
|
return;
|
|
191
|
+
// Clear previous script results so only the current script shows a status
|
|
192
|
+
setScriptResults({});
|
|
190
193
|
setRunningScripts((prev) => new Set(prev).add(scriptId));
|
|
191
|
-
setScriptResults((prev) => ({ ...prev, [scriptId]: undefined }));
|
|
192
194
|
try {
|
|
193
195
|
await script.run(context);
|
|
194
196
|
setScriptResults((prev) => ({
|
|
@@ -733,51 +735,71 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
|
|
|
733
735
|
acc[category].push(script);
|
|
734
736
|
return acc;
|
|
735
737
|
}, {});
|
|
736
|
-
return Object.entries(grouped).map(([category, scripts]) =>
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
738
|
+
return Object.entries(grouped).map(([category, scripts]) => {
|
|
739
|
+
const isExpanded = expandedScriptCategories[category] ?? false;
|
|
740
|
+
const toggleCategory = () => {
|
|
741
|
+
setExpandedScriptCategories((prev) => ({
|
|
742
|
+
...prev,
|
|
743
|
+
[category]: !(prev[category] ?? false),
|
|
744
|
+
}));
|
|
745
|
+
};
|
|
746
|
+
return (_jsxs("div", { children: [_jsx("button", { type: "button", onClick: toggleCategory, style: {
|
|
747
|
+
display: 'flex',
|
|
748
|
+
alignItems: 'center',
|
|
749
|
+
justifyContent: 'space-between',
|
|
750
|
+
width: '100%',
|
|
751
|
+
background: 'none',
|
|
752
|
+
border: 'none',
|
|
753
|
+
padding: '6px 0',
|
|
754
|
+
cursor: 'pointer',
|
|
755
|
+
}, children: _jsxs("div", { style: {
|
|
756
|
+
display: 'flex',
|
|
757
|
+
alignItems: 'center',
|
|
758
|
+
gap: '6px',
|
|
759
|
+
fontSize: '11px',
|
|
760
|
+
fontWeight: 'bold',
|
|
761
|
+
textTransform: 'uppercase',
|
|
762
|
+
letterSpacing: '0.5px',
|
|
763
|
+
color: '#9ca3af',
|
|
764
|
+
}, children: [_jsx("span", { style: { fontSize: '10px' }, children: isExpanded ? '▼' : '▶' }), _jsx("span", { children: category }), _jsxs("span", { style: { fontSize: '10px', color: '#6b7280' }, children: ["(", scripts.length, ")"] })] }) }), isExpanded && (_jsx("div", { style: { display: 'grid', gap: '8px', marginTop: '4px' }, children: scripts.map((script) => {
|
|
765
|
+
const isRunning = runningScripts.has(script.id);
|
|
766
|
+
const result = scriptResults[script.id];
|
|
767
|
+
return (_jsxs("div", { style: {
|
|
768
|
+
border: '1px solid #374151',
|
|
769
|
+
borderRadius: '6px',
|
|
770
|
+
padding: '10px 12px',
|
|
771
|
+
backgroundColor: '#111827',
|
|
772
|
+
}, children: [_jsxs("div", { style: {
|
|
773
|
+
display: 'flex',
|
|
774
|
+
justifyContent: 'space-between',
|
|
775
|
+
alignItems: 'flex-start',
|
|
776
|
+
gap: '12px',
|
|
777
|
+
}, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: {
|
|
778
|
+
color: '#f9fafb',
|
|
779
|
+
fontWeight: 'bold',
|
|
780
|
+
fontSize: '12px',
|
|
781
|
+
marginBottom: '4px',
|
|
782
|
+
}, children: script.name }), script.description && (_jsx("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: script.description }))] }), _jsx("button", { onClick: () => handleRunScript(script.id), disabled: isRunning, style: {
|
|
783
|
+
backgroundColor: isRunning ? '#374151' : '#3b82f6',
|
|
784
|
+
color: '#fff',
|
|
785
|
+
border: 'none',
|
|
786
|
+
borderRadius: '4px',
|
|
787
|
+
padding: '6px 12px',
|
|
788
|
+
fontSize: '11px',
|
|
789
|
+
fontWeight: 'bold',
|
|
790
|
+
cursor: isRunning ? 'not-allowed' : 'pointer',
|
|
791
|
+
transition: 'background-color 0.2s',
|
|
792
|
+
minWidth: '60px',
|
|
793
|
+
}, children: isRunning ? '⏳' : '▶ Run' })] }), result && (_jsxs("div", { style: {
|
|
794
|
+
marginTop: '8px',
|
|
795
|
+
padding: '6px 8px',
|
|
796
|
+
borderRadius: '4px',
|
|
797
|
+
fontSize: '10px',
|
|
798
|
+
backgroundColor: result.success ? '#065f46' : '#7f1d1d',
|
|
799
|
+
color: result.success ? '#6ee7b7' : '#fca5a5',
|
|
800
|
+
}, children: [result.success ? '✅' : '❌', " ", result.message] }))] }, script.id));
|
|
801
|
+
}) }))] }, category));
|
|
802
|
+
});
|
|
781
803
|
})() })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No debug scripts available" }))] })), activeTab === 'raw' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Raw Context Data" }), _jsx("div", { style: { fontSize: '12px' }, children: _jsx(TreeView, { data: context, name: "tagadaContext", maxLevel: 4 }) })] }))] })] })] }));
|
|
782
804
|
};
|
|
783
805
|
export default DebugDrawer;
|