@tagadapay/plugin-sdk 3.1.11 → 3.1.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.
Files changed (116) hide show
  1. package/README.md +1129 -1129
  2. package/build-cdn.js +231 -228
  3. package/dist/data/iso3166.d.ts +23 -33
  4. package/dist/data/iso3166.js +134 -198
  5. package/dist/data/languages.d.ts +5 -64
  6. package/dist/data/languages.js +23 -143
  7. package/dist/external-tracker.js +968 -102
  8. package/dist/external-tracker.min.js +2 -2
  9. package/dist/external-tracker.min.js.map +4 -4
  10. package/dist/react/hooks/useISOData.js +1 -1
  11. package/dist/react/hooks/usePaymentPolling.d.ts +3 -3
  12. package/dist/react/hooks/useShippingRates.d.ts +6 -0
  13. package/dist/react/hooks/useShippingRates.js +38 -0
  14. package/dist/react/providers/TagadaProvider.js +5 -5
  15. package/dist/react/services/apiService.d.ts +21 -0
  16. package/dist/react/services/apiService.js +10 -0
  17. package/dist/tagada-sdk.js +2079 -179
  18. package/dist/tagada-sdk.min.js +4 -2
  19. package/dist/tagada-sdk.min.js.map +4 -4
  20. package/dist/v2/core/client.d.ts +4 -2
  21. package/dist/v2/core/client.js +4 -3
  22. package/dist/v2/core/errors.d.ts +75 -0
  23. package/dist/v2/core/errors.js +104 -0
  24. package/dist/v2/core/funnelClient.d.ts +16 -15
  25. package/dist/v2/core/funnelClient.js +1 -1
  26. package/dist/v2/core/index.d.ts +1 -0
  27. package/dist/v2/core/index.js +2 -0
  28. package/dist/v2/core/pixelMapping.d.ts +49 -0
  29. package/dist/v2/core/pixelMapping.js +325 -0
  30. package/dist/v2/core/resources/apiClient.d.ts +2 -0
  31. package/dist/v2/core/resources/apiClient.js +52 -9
  32. package/dist/v2/core/resources/checkout.d.ts +89 -30
  33. package/dist/v2/core/resources/checkout.js +8 -0
  34. package/dist/v2/core/resources/customer.d.ts +20 -19
  35. package/dist/v2/core/resources/funnel.d.ts +17 -17
  36. package/dist/v2/core/resources/payments.d.ts +84 -13
  37. package/dist/v2/core/resources/payments.js +26 -9
  38. package/dist/v2/core/resources/shippingRates.d.ts +15 -0
  39. package/dist/v2/core/resources/shippingRates.js +11 -0
  40. package/dist/v2/core/types.d.ts +50 -12
  41. package/dist/v2/core/types.js +0 -3
  42. package/dist/v2/core/utils/checkout.d.ts +2 -2
  43. package/dist/v2/core/utils/checkout.js +7 -2
  44. package/dist/v2/core/utils/order.d.ts +11 -9
  45. package/dist/v2/core/utils/previewModeIndicator.js +101 -101
  46. package/dist/v2/index.d.ts +4 -2
  47. package/dist/v2/index.js +1 -1
  48. package/dist/v2/react/components/ApplePayButton.js +13 -4
  49. package/dist/v2/react/components/FunnelScriptInjector.js +51 -30
  50. package/dist/v2/react/components/WhopCheckout.d.ts +24 -0
  51. package/dist/v2/react/components/WhopCheckout.js +231 -0
  52. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +1 -1
  53. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.d.ts +14 -0
  54. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.js +181 -0
  55. package/dist/v2/react/hooks/payment-actions/useErrorAction.d.ts +9 -0
  56. package/dist/v2/react/hooks/payment-actions/useErrorAction.js +21 -0
  57. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.d.ts +14 -0
  58. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.js +187 -0
  59. package/dist/v2/react/hooks/payment-actions/useKessPayAction.d.ts +11 -0
  60. package/dist/v2/react/hooks/payment-actions/useKessPayAction.js +91 -0
  61. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.d.ts +24 -0
  62. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.js +221 -0
  63. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.d.ts +15 -0
  64. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.js +142 -0
  65. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.d.ts +3 -0
  66. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.js +13 -0
  67. package/dist/v2/react/hooks/payment-actions/useRedirectAction.d.ts +10 -0
  68. package/dist/v2/react/hooks/payment-actions/useRedirectAction.js +35 -0
  69. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.d.ts +14 -0
  70. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.js +192 -0
  71. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.d.ts +14 -0
  72. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.js +81 -0
  73. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.d.ts +11 -0
  74. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.js +84 -0
  75. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.d.ts +14 -0
  76. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.js +36 -0
  77. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.d.ts +31 -0
  78. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.js +212 -0
  79. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.d.ts +14 -0
  80. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.js +207 -0
  81. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.d.ts +12 -0
  82. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.js +101 -0
  83. package/dist/v2/react/hooks/useCheckoutQuery.d.ts +6 -0
  84. package/dist/v2/react/hooks/useCheckoutQuery.js +45 -0
  85. package/dist/v2/react/hooks/useFunnel.d.ts +1 -2
  86. package/dist/v2/react/hooks/useGeoLocation.d.ts +2 -1
  87. package/dist/v2/react/hooks/useGeoLocation.js +4 -2
  88. package/dist/v2/react/hooks/useGoogleAutocomplete.js +82 -33
  89. package/dist/v2/react/hooks/useISOData.js +1 -1
  90. package/dist/v2/react/hooks/usePaymentPolling.d.ts +3 -3
  91. package/dist/v2/react/hooks/usePaymentQuery.d.ts +18 -5
  92. package/dist/v2/react/hooks/usePaymentQuery.js +63 -1015
  93. package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +3 -2
  94. package/dist/v2/react/hooks/usePaymentRetrieve.js +3 -1
  95. package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -43
  96. package/dist/v2/react/hooks/usePixelTracking.js +213 -407
  97. package/dist/v2/react/hooks/useShippingRatesQuery.d.ts +6 -0
  98. package/dist/v2/react/hooks/useShippingRatesQuery.js +47 -4
  99. package/dist/v2/react/hooks/useStepConfig.d.ts +2 -8
  100. package/dist/v2/react/hooks/useStepConfig.js +1 -1
  101. package/dist/v2/react/hooks/useWhopPaymentPolling.d.ts +30 -0
  102. package/dist/v2/react/hooks/useWhopPaymentPolling.js +61 -0
  103. package/dist/v2/react/index.d.ts +7 -0
  104. package/dist/v2/react/index.js +4 -0
  105. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +2 -1
  106. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +3 -1
  107. package/dist/v2/react/providers/TagadaProvider.js +76 -7
  108. package/dist/v2/standalone/external-tracker.d.ts +52 -46
  109. package/dist/v2/standalone/external-tracker.js +205 -98
  110. package/dist/v2/standalone/index.d.ts +22 -0
  111. package/dist/v2/standalone/index.js +125 -0
  112. package/package.json +112 -112
  113. package/dist/react/utils/__tests__/urlUtils.test.d.ts +0 -1
  114. package/dist/react/utils/__tests__/urlUtils.test.js +0 -189
  115. package/dist/v2/core/__tests__/pathRemapping.test.d.ts +0 -11
  116. package/dist/v2/core/__tests__/pathRemapping.test.js +0 -776
@@ -1,36 +1,33 @@
1
1
  /**
2
2
  * TagadaPay External Page Tracker
3
3
  *
4
- * A lightweight standalone script for tracking users on external pages
5
- * that are part of a Tagadapay funnel but not hosted on the Tagadapay platform.
4
+ * Standalone script for tracking users on external pages that are part of a
5
+ * TagadaPay funnel but not hosted on the TagadaPay platform.
6
6
  *
7
- * ARCHITECTURE:
8
- * - Reuses core SDK infrastructure (TagadaClient) for authentication and API handling
9
- * - All tracking handled automatically by funnelOrchestrator via autoInitialize() and navigate()
10
- * - No separate tracking endpoints needed - unified tracking through orchestrator
7
+ * Use cases:
8
+ * - WooCommerce / WordPress storefronts
9
+ * - Custom landing pages
10
+ * - Any external page that is a funnel step
11
11
  *
12
- * Usage (via CDN):
12
+ * @example CDN usage
13
+ * ```html
13
14
  * <script src="https://cdn.jsdelivr.net/npm/@tagadapay/plugin-sdk/dist/external-tracker.min.js"></script>
14
15
  * <script>
15
16
  * TagadaTracker.init({
16
17
  * storeId: 'store_xxx',
17
18
  * accountId: 'acc_xxx',
18
- * funnelId: 'funnel_xxx', // Optional: detected from URL
19
19
  * stepId: 'step_xxx',
20
- * stepName: 'External Offer Page',
21
- * stepType: 'external'
22
- * });
23
- *
24
- * // Navigate to next step (tracking automatic)
25
- * TagadaTracker.navigate({
26
- * eventType: 'form.submitted',
27
- * eventData: { email: 'user@example.com' }
28
20
  * });
29
21
  * </script>
22
+ * ```
30
23
  */
31
24
  import { createTagadaClient } from './index';
32
25
  import { setClientToken } from '../core/utils/tokenStorage';
33
26
  // ============================================================================
27
+ // VERSION
28
+ // ============================================================================
29
+ export const TRACKER_VERSION = '1.0.0';
30
+ // ============================================================================
34
31
  // UTILITIES
35
32
  // ============================================================================
36
33
  function getUrlParam(name) {
@@ -44,6 +41,45 @@ function log(debug, ...args) {
44
41
  console.log('[TagadaTracker]', ...args);
45
42
  }
46
43
  }
44
+ function warn(...args) {
45
+ console.warn('[TagadaTracker]', ...args);
46
+ }
47
+ function validate(config) {
48
+ if (!config.storeId || typeof config.storeId !== 'string') {
49
+ throw new Error('TagadaTracker: storeId is required and must be a non-empty string.');
50
+ }
51
+ if (!config.accountId || typeof config.accountId !== 'string') {
52
+ throw new Error('TagadaTracker: accountId is required and must be a non-empty string.');
53
+ }
54
+ if (!config.stepId || typeof config.stepId !== 'string') {
55
+ throw new Error('TagadaTracker: stepId is required and must be a non-empty string.');
56
+ }
57
+ if (config.apiBaseUrl) {
58
+ try {
59
+ new URL(config.apiBaseUrl);
60
+ }
61
+ catch {
62
+ throw new Error(`TagadaTracker: apiBaseUrl is not a valid URL: "${config.apiBaseUrl}"`);
63
+ }
64
+ }
65
+ }
66
+ async function retryWithBackoff(fn, maxRetries, debug) {
67
+ let lastError;
68
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
69
+ try {
70
+ return await fn();
71
+ }
72
+ catch (err) {
73
+ lastError = err instanceof Error ? err : new Error(String(err));
74
+ if (attempt < maxRetries) {
75
+ const delay = Math.min(1000 * 2 ** attempt, 8000);
76
+ log(debug, `Retry ${attempt + 1}/${maxRetries} in ${delay}ms...`);
77
+ await new Promise((r) => setTimeout(r, delay));
78
+ }
79
+ }
80
+ }
81
+ throw lastError;
82
+ }
47
83
  // ============================================================================
48
84
  // MAIN CLASS
49
85
  // ============================================================================
@@ -53,41 +89,67 @@ class TagadaExternalTracker {
53
89
  this.client = null;
54
90
  this.initialized = false;
55
91
  this.initializing = false;
92
+ this.unsubscribe = null;
93
+ /** Tracker version */
94
+ this.version = TRACKER_VERSION;
56
95
  }
57
96
  /**
58
- * Initialize the tracker using SDK infrastructure
97
+ * Initialize the tracker.
98
+ * When `onError` is provided, errors are passed to the callback and init()
99
+ * resolves to `null` instead of throwing.
59
100
  */
60
101
  async init(config) {
61
- if (this.initialized || this.initializing) {
62
- log(config.debug || false, 'Already initialized or initializing');
102
+ if (this.initialized) {
103
+ log(config.debug || false, 'Already initialized returning existing session.');
63
104
  return this.getSession();
64
105
  }
106
+ if (this.initializing) {
107
+ log(config.debug || false, 'Initialization in progress — skipping duplicate call.');
108
+ return null;
109
+ }
65
110
  this.initializing = true;
66
- this.config = {
67
- debug: false,
68
- ...config,
69
- };
70
- log(this.config.debug, '🚀 Initializing external tracker with SDK...', config);
111
+ this.config = { debug: false, ...config };
112
+ const debug = this.config.debug;
113
+ try {
114
+ validate(this.config);
115
+ }
116
+ catch (err) {
117
+ this.initializing = false;
118
+ const error = err instanceof Error ? err : new Error(String(err));
119
+ if (this.config.onError) {
120
+ this.config.onError(error);
121
+ return null;
122
+ }
123
+ throw error;
124
+ }
125
+ log(debug, `🚀 Initializing external tracker v${TRACKER_VERSION}`, {
126
+ storeId: config.storeId,
127
+ accountId: config.accountId,
128
+ stepId: config.stepId,
129
+ funnelId: config.funnelId,
130
+ });
71
131
  try {
72
- // 1. Check for token in URL and save to storage (bootstrap auth)
73
- // TagadaClient will automatically pick it up from storage
74
132
  const urlToken = getUrlParam('token');
75
133
  if (urlToken) {
76
134
  setClientToken(urlToken);
77
- log(this.config.debug, '🔑 Bootstrapped token from URL');
135
+ log(debug, '🔑 Bootstrapped token from URL');
78
136
  }
79
- // 2. Create TagadaClient
80
137
  this.client = createTagadaClient({
81
- debugMode: this.config.debug,
82
- features: { funnel: true },
138
+ debugMode: debug,
139
+ features: { funnel: { skipAutoInit: true } },
140
+ rawPluginConfig: {
141
+ storeId: this.config.storeId,
142
+ accountId: this.config.accountId,
143
+ },
144
+ customApiConfig: this.config.apiBaseUrl ? {
145
+ apiConfig: {
146
+ baseUrl: this.config.apiBaseUrl.trim(),
147
+ },
148
+ } : undefined,
83
149
  });
84
- // 3. Wait for client to be ready (load token, init auth state)
85
150
  await this.waitForClientReady();
86
- // 4. Auto-initialize funnel session
87
- // FunnelClient handles cookies, existing session restoration, etc.
88
- // Orchestrator automatically tracks session start and step view
89
- const funnelContext = await this.initializeFunnel();
90
- log(this.config.debug, '✅ Session initialized (tracking handled by orchestrator):', funnelContext);
151
+ const funnelContext = await retryWithBackoff(() => this.initializeFunnel(), 2, debug);
152
+ log(debug, '✅ Session initialized:', funnelContext);
91
153
  this.initialized = true;
92
154
  const session = this.getSession();
93
155
  if (session) {
@@ -95,19 +157,20 @@ class TagadaExternalTracker {
95
157
  }
96
158
  return session;
97
159
  }
98
- catch (error) {
99
- const err = error instanceof Error ? error : new Error(String(error));
100
- log(this.config.debug, '❌ Initialization failed:', err);
101
- this.config.onError?.(err);
102
- throw err;
160
+ catch (err) {
161
+ const error = err instanceof Error ? err : new Error(String(err));
162
+ log(debug, '❌ Initialization failed:', error);
163
+ if (this.config.onError) {
164
+ this.config.onError(error);
165
+ return null;
166
+ }
167
+ throw error;
103
168
  }
104
169
  finally {
105
170
  this.initializing = false;
106
171
  }
107
172
  }
108
- /**
109
- * Get current session from SDK state
110
- */
173
+ /** Get current session data. */
111
174
  getSession() {
112
175
  if (!this.client?.funnel?.state.context)
113
176
  return null;
@@ -121,31 +184,27 @@ class TagadaExternalTracker {
121
184
  cmsToken: this.client.state.token || undefined,
122
185
  };
123
186
  }
124
- /**
125
- * Check if tracker is ready
126
- */
187
+ /** Whether the tracker is fully initialized and ready. */
127
188
  isReady() {
128
189
  return this.initialized && !!this.client?.funnel?.state.context;
129
190
  }
130
191
  /**
131
- * Navigate to next step in funnel using SDK's funnel client
192
+ * Navigate to the next step in the funnel.
193
+ * By default, auto-redirects the browser window.
132
194
  */
133
195
  async navigate(options) {
134
196
  if (!this.isReady()) {
135
- throw new Error('Tracker not initialized. Call init() first.');
197
+ throw new Error('TagadaTracker: not initialized. Call init() first.');
136
198
  }
137
199
  log(this.config.debug, '🚀 Navigating:', options);
138
- // Determine if we should auto-redirect (default: true)
139
200
  const shouldAutoRedirect = options.autoRedirect !== false;
140
201
  try {
141
202
  const result = await this.client.funnel.navigate({
142
203
  type: options.eventType,
143
204
  data: options.eventData || {},
144
- }, { autoRedirect: false } // Always disable SDK auto-redirect, we handle it here
145
- );
205
+ }, { autoRedirect: false });
146
206
  if (result?.url) {
147
207
  log(this.config.debug, '✅ Navigation result:', result.url);
148
- // Only redirect if autoRedirect is enabled
149
208
  if (shouldAutoRedirect && typeof window !== 'undefined') {
150
209
  window.location.href = options.returnUrl || result.url;
151
210
  }
@@ -159,37 +218,51 @@ class TagadaExternalTracker {
159
218
  }
160
219
  }
161
220
  /**
162
- * Get customer ID (for identifying the user)
221
+ * Track a custom event (e.g., button click, scroll depth, video play).
222
+ * Events are sent through the funnel orchestrator for unified analytics.
163
223
  */
224
+ async trackEvent(options) {
225
+ if (!this.isReady()) {
226
+ warn('trackEvent called before init — event dropped:', options.name);
227
+ return;
228
+ }
229
+ log(this.config.debug, '📊 Tracking event:', options.name, options.data);
230
+ try {
231
+ await this.client.funnel.navigate({
232
+ type: options.name,
233
+ data: options.data || {},
234
+ }, { autoRedirect: false });
235
+ }
236
+ catch {
237
+ // Non-critical — swallow errors for tracking events
238
+ log(this.config.debug, '⚠️ Event tracking failed (non-critical):', options.name);
239
+ }
240
+ }
241
+ /** Get customer ID. */
164
242
  getCustomerId() {
165
- return this.client?.state.auth.customer?.id || this.client?.funnel?.state.context?.customerId || null;
243
+ return this.client?.state.auth.customer?.id
244
+ || this.client?.funnel?.state.context?.customerId
245
+ || null;
166
246
  }
167
- /**
168
- * Get funnel session ID
169
- */
247
+ /** Get funnel session ID. */
170
248
  getFunnelSessionId() {
171
249
  return this.client?.funnel?.state.context?.sessionId || null;
172
250
  }
173
251
  /**
174
- * Build a URL with funnel context parameters
175
- * Useful for linking to other external pages while preserving session
252
+ * Build a URL that preserves funnel session context.
253
+ * Use this to link to other external pages within the same funnel.
176
254
  */
177
255
  buildUrl(baseUrl, additionalParams) {
178
256
  const session = this.getSession();
179
- if (!session) {
257
+ if (!session)
180
258
  return baseUrl;
181
- }
182
259
  const url = new URL(baseUrl, typeof window !== 'undefined' ? window.location.origin : undefined);
183
- // Add funnel session context
184
260
  url.searchParams.set('funnelSessionId', session.sessionId);
185
- if (session.cmsToken) {
261
+ if (session.cmsToken)
186
262
  url.searchParams.set('token', session.cmsToken);
187
- }
188
- if (session.funnelId) {
263
+ if (session.funnelId)
189
264
  url.searchParams.set('funnelId', session.funnelId);
190
- }
191
265
  url.searchParams.set('storeId', session.storeId);
192
- // Add any additional params
193
266
  if (additionalParams) {
194
267
  Object.entries(additionalParams).forEach(([key, value]) => {
195
268
  url.searchParams.set(key, value);
@@ -197,60 +270,94 @@ class TagadaExternalTracker {
197
270
  }
198
271
  return url.toString();
199
272
  }
200
- /**
201
- * Get the underlying SDK client (for advanced usage)
202
- */
273
+ /** Get the underlying SDK client (advanced usage). */
203
274
  getClient() {
204
275
  return this.client;
205
276
  }
277
+ /**
278
+ * Reset the tracker to a new step without re-creating the session.
279
+ * Useful for SPAs that navigate between funnel steps client-side.
280
+ */
281
+ async reset(newStepId) {
282
+ if (!this.client || !this.config) {
283
+ throw new Error('TagadaTracker: not initialized. Call init() first.');
284
+ }
285
+ log(this.config.debug, '🔄 Resetting to step:', newStepId);
286
+ this.config.stepId = newStepId;
287
+ const ctx = await this.initializeFunnel();
288
+ const session = this.getSession();
289
+ if (session)
290
+ this.config.onReady?.(session);
291
+ return session;
292
+ }
293
+ /**
294
+ * Destroy the tracker, clean up event listeners and state.
295
+ * Call this when the tracker is no longer needed (e.g., SPA teardown).
296
+ */
297
+ destroy() {
298
+ if (this.unsubscribe) {
299
+ this.unsubscribe();
300
+ this.unsubscribe = null;
301
+ }
302
+ if (this.client) {
303
+ this.client.destroy?.();
304
+ }
305
+ this.client = null;
306
+ this.config = null;
307
+ this.initialized = false;
308
+ this.initializing = false;
309
+ log(false, '🗑️ Tracker destroyed');
310
+ }
206
311
  // ========================================================================
207
312
  // PRIVATE METHODS
208
313
  // ========================================================================
209
314
  async waitForClientReady() {
210
315
  if (!this.client)
211
316
  return;
212
- // Wait for token/auth to be resolved
317
+ // Wait for isInitialized which is set AFTER the full init sequence:
318
+ // anonymous token → session/v2/init → isInitialized=true
319
+ // Do NOT resolve on token alone — that fires before session init.
213
320
  return new Promise((resolve) => {
214
- let retries = 0;
215
- const checkReady = () => {
216
- // Check if initialized OR if we have a token (sometimes isInitialized is lazy)
217
- if (this.client?.state.isInitialized || this.client?.state.token) {
321
+ if (this.client?.state.isInitialized) {
322
+ resolve();
323
+ return;
324
+ }
325
+ let resolved = false;
326
+ const timeout = setTimeout(() => {
327
+ if (!resolved) {
328
+ resolved = true;
329
+ log(this.config?.debug || false, '⏱️ Client ready timeout — proceeding');
218
330
  resolve();
219
331
  }
220
- else if (retries > 40) { // 2 seconds timeout
221
- resolve(); // Proceed anyway (might be anonymous)
222
- }
223
- else {
224
- retries++;
225
- setTimeout(checkReady, 50);
332
+ }, 10000);
333
+ this.unsubscribe = this.client.subscribe(() => {
334
+ if (!resolved && this.client?.state.isInitialized) {
335
+ resolved = true;
336
+ clearTimeout(timeout);
337
+ resolve();
226
338
  }
227
- };
228
- checkReady();
339
+ });
229
340
  });
230
341
  }
231
342
  async initializeFunnel() {
232
343
  if (!this.client?.funnel)
233
344
  return null;
234
- // Prepare auth session object
345
+ const customerId = this.client.state.auth.customer?.id;
346
+ const sessionId = this.client.state.auth.session?.sessionId;
347
+ if (!customerId && !sessionId) {
348
+ warn('No auth session available — funnel init may fail.');
349
+ }
235
350
  const authSession = {
236
- customerId: this.client.state.auth.customer?.id || 'anon_placeholder',
237
- sessionId: this.client.state.auth.session?.sessionId || 'sess_placeholder',
351
+ customerId: customerId || 'anon_placeholder',
352
+ sessionId: sessionId || 'sess_placeholder',
238
353
  };
239
354
  const store = {
240
355
  id: this.config.storeId,
241
- accountId: this.config.accountId || '',
356
+ accountId: this.config.accountId,
242
357
  };
243
- // IMPORTANT: For external pages, we must explicitly pass stepId as entryStepId
244
- // because URL-to-step mapping won't work for external URLs not hosted on Tagadapay
245
358
  const entryStepId = this.config.stepId;
246
- if (!entryStepId) {
247
- throw new Error('stepId is required for external page tracking (URL mapping does not work for external pages)');
248
- }
249
- log(this.config.debug, '🔍 Initializing external page at step:', entryStepId);
250
- // Use initialize() (not autoInitialize()) to explicitly specify the step
251
- // Orchestrator will automatically track session start and step view at this step
252
- return this.client.funnel.initialize(authSession, store, this.config.funnelId || getUrlParam('funnelId') || undefined, entryStepId // ✅ Explicitly tell orchestrator which step we're on
253
- );
359
+ log(this.config.debug, '🔍 Initializing funnel at step:', entryStepId);
360
+ return this.client.funnel.initialize(authSession, store, this.config.funnelId || getUrlParam('funnelId') || undefined, entryStepId);
254
361
  }
255
362
  }
256
363
  // ============================================================================
@@ -9,15 +9,37 @@
9
9
  import { TagadaClient, TagadaClientConfig, TagadaState } from '../core/client';
10
10
  import { ApiClient } from '../core/resources/apiClient';
11
11
  import { CheckoutResource } from '../core/resources/checkout';
12
+ /**
13
+ * Auto-inject all stepConfig scripts
14
+ * Called automatically when SDK loads
15
+ * Can also be called manually if needed (e.g., after dynamic config update)
16
+ */
17
+ export declare function injectStepConfigScripts(): void;
12
18
  /**
13
19
  * Factory function to create a Tagada Client instance.
14
20
  * Features (like funnel) can be toggled via the config.
15
21
  */
16
22
  export declare function createTagadaClient(config?: TagadaClientConfig): TagadaClient;
17
23
  export { TagadaClient, ApiClient, CheckoutResource };
24
+ export { ShippingRatesResource } from '../core/resources/shippingRates';
25
+ export { PaymentsResource } from '../core/resources/payments';
26
+ export { OrdersResource } from '../core/resources/orders';
27
+ export type { ShippingRate, ShippingRatesResponse, ShippingRatesPreviewParams } from '../core/resources/shippingRates';
28
+ export type { Payment, PaymentResponse, CardPaymentMethod, BasisTheoryInstance, GooglePayToken, PaymentInstrumentInput, } from '../core/resources/payments';
29
+ export { ISODataCore } from '../core/isoData';
30
+ export type { ISOCountry, ISORegion } from '../core/isoData';
31
+ export { GoogleAutocompleteCore } from '../core/googleAutocomplete';
32
+ export type { GooglePrediction, GooglePlaceDetails, AddressComponents } from '../core/googleAutocomplete';
33
+ export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
34
+ export type { TagadaErrorOptions, TagadaErrorCodeValue } from '../core/errors';
18
35
  export type { TagadaClientConfig, TagadaState };
19
36
  export { FunnelActionType } from '../core/resources/funnel';
20
37
  export type { FunnelAction, FunnelNavigationResult, SimpleFunnelContext } from '../core/resources/funnel';
38
+ export type { CheckoutData, CheckoutSession, CheckoutSummary, CheckoutSummaryItem, CheckoutLineItem, CheckoutInitParams, Promotion, } from '../core/resources/checkout';
39
+ export type { Order, OrderItem, OrderAddress, OrderSummary, OrderWithRelations, PaymentSummary, PromotionSummary, Subscription, DeviceInfo, PromotionCode, Customer, Store, PickupPoint, } from '../core/types';
21
40
  export * from '../core/utils';
41
+ export { matchRoute, getInternalPath, isPathRemapped, getPathInfo, } from '../core/pathRemapping';
42
+ export { resolvePixelEvents, mapMetaEvent, mapTikTokEvent, mapSnapchatEvent, mapPinterestEvent, mapGTMEvent, isEventEnabled, getEligiblePixels, applyGoogleAdsConversion, } from '../core/pixelMapping';
43
+ export type { StandardPixelEvent, PixelProviderKey, MappedEvent, ProviderEvent, } from '../core/pixelMapping';
22
44
  export { TagadaTracker, TagadaExternalTracker, } from './external-tracker';
23
45
  export type { TagadaTrackerConfig, ExternalTrackerSession, NavigateOptions, } from './external-tracker';
@@ -9,6 +9,117 @@
9
9
  import { TagadaClient } from '../core/client';
10
10
  import { ApiClient } from '../core/resources/apiClient';
11
11
  import { CheckoutResource } from '../core/resources/checkout';
12
+ import { getAssignedStepConfig } from '../core/funnelClient';
13
+ /**
14
+ * Parse step config from window variable or meta tag
15
+ */
16
+ function parseStepConfigScripts() {
17
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
18
+ return [];
19
+ }
20
+ // Try to get stepConfig (uses same logic as getAssignedStepConfig)
21
+ const stepConfig = getAssignedStepConfig();
22
+ if (stepConfig?.scripts) {
23
+ return stepConfig.scripts.filter(s => s.enabled);
24
+ }
25
+ return [];
26
+ }
27
+ /**
28
+ * Inject a script at the specified position
29
+ */
30
+ function injectScript(script, index) {
31
+ const position = script.position || 'body-end';
32
+ const scriptId = `tagada-stepconfig-script-${index}`;
33
+ // Skip if already injected
34
+ if (document.getElementById(scriptId)) {
35
+ return;
36
+ }
37
+ // Extract script content (remove <script> tags if present)
38
+ let scriptBody = script.content.trim();
39
+ const scriptTagMatch = scriptBody.match(/^<script[^>]*>([\s\S]*)<\/script>$/i);
40
+ if (scriptTagMatch) {
41
+ scriptBody = scriptTagMatch[1].trim();
42
+ }
43
+ if (!scriptBody)
44
+ return;
45
+ // Wrap script content with error handling
46
+ // NOTE: Use string concatenation instead of template literals to avoid breaking
47
+ // when scriptBody contains backticks or ${...} expressions
48
+ const wrappedScript = '(function() {\n' +
49
+ ' try {\n' +
50
+ ' // Script: ' + script.name + '\n' +
51
+ scriptBody + '\n' +
52
+ ' } catch (error) {\n' +
53
+ ' console.error("[TagadaPay] StepConfig script error:", error);\n' +
54
+ ' }\n' +
55
+ '})();';
56
+ // Create script element
57
+ const scriptElement = document.createElement('script');
58
+ scriptElement.id = scriptId;
59
+ scriptElement.setAttribute('data-tagada-stepconfig-script', 'true');
60
+ scriptElement.setAttribute('data-script-name', script.name);
61
+ scriptElement.textContent = wrappedScript;
62
+ // Inject at the correct position
63
+ switch (position) {
64
+ case 'head-start':
65
+ if (document.head.firstChild) {
66
+ document.head.insertBefore(scriptElement, document.head.firstChild);
67
+ }
68
+ else {
69
+ document.head.appendChild(scriptElement);
70
+ }
71
+ break;
72
+ case 'head-end':
73
+ document.head.appendChild(scriptElement);
74
+ break;
75
+ case 'body-start':
76
+ if (document.body.firstChild) {
77
+ document.body.insertBefore(scriptElement, document.body.firstChild);
78
+ }
79
+ else {
80
+ document.body.appendChild(scriptElement);
81
+ }
82
+ break;
83
+ case 'body-end':
84
+ default:
85
+ document.body.appendChild(scriptElement);
86
+ break;
87
+ }
88
+ }
89
+ /**
90
+ * Auto-inject all stepConfig scripts
91
+ * Called automatically when SDK loads
92
+ * Can also be called manually if needed (e.g., after dynamic config update)
93
+ */
94
+ export function injectStepConfigScripts() {
95
+ const scripts = parseStepConfigScripts();
96
+ if (scripts.length === 0)
97
+ return;
98
+ scripts.forEach((script, index) => {
99
+ injectScript(script, index);
100
+ });
101
+ }
102
+ // Auto-run script injection when SDK loads
103
+ // Uses requestIdleCallback or setTimeout fallback for non-blocking execution
104
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
105
+ const runInjection = () => {
106
+ // Wait for body to be available
107
+ if (document.body) {
108
+ injectStepConfigScripts();
109
+ }
110
+ else {
111
+ // Body not ready, wait for DOMContentLoaded
112
+ document.addEventListener('DOMContentLoaded', injectStepConfigScripts, { once: true });
113
+ }
114
+ };
115
+ // Run after current script execution completes
116
+ if ('requestIdleCallback' in window) {
117
+ window.requestIdleCallback(runInjection, { timeout: 100 });
118
+ }
119
+ else {
120
+ setTimeout(runInjection, 0);
121
+ }
122
+ }
12
123
  /**
13
124
  * Factory function to create a Tagada Client instance.
14
125
  * Features (like funnel) can be toggled via the config.
@@ -18,9 +129,23 @@ export function createTagadaClient(config = {}) {
18
129
  }
19
130
  // Re-export Core Classes
20
131
  export { TagadaClient, ApiClient, CheckoutResource };
132
+ // Re-export Resource Classes (for standalone resolvers / builders)
133
+ export { ShippingRatesResource } from '../core/resources/shippingRates';
134
+ export { PaymentsResource } from '../core/resources/payments';
135
+ export { OrdersResource } from '../core/resources/orders';
136
+ // Re-export ISO Data Core (for standalone address form / resolvers)
137
+ export { ISODataCore } from '../core/isoData';
138
+ // Re-export Google Autocomplete Core (for standalone address form)
139
+ export { GoogleAutocompleteCore } from '../core/googleAutocomplete';
140
+ // Re-export Error Types
141
+ export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
21
142
  export { FunnelActionType } from '../core/resources/funnel';
22
143
  // Re-export Utilities (includes formatMoney from core/utils/currency)
23
144
  export * from '../core/utils';
145
+ // Re-export path remapping utilities (for SPA routing)
146
+ export { matchRoute, getInternalPath, isPathRemapped, getPathInfo, } from '../core/pathRemapping';
147
+ // Re-export pixel mapping (for standalone pixel tracking)
148
+ export { resolvePixelEvents, mapMetaEvent, mapTikTokEvent, mapSnapchatEvent, mapPinterestEvent, mapGTMEvent, isEventEnabled, getEligiblePixels, applyGoogleAdsConversion, } from '../core/pixelMapping';
24
149
  // ============================================================================
25
150
  // EXTERNAL PAGE TRACKER
26
151
  // ============================================================================