@tagadapay/plugin-sdk 3.1.5 → 3.1.9

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 (71) hide show
  1. package/README.md +1129 -1129
  2. package/build-cdn.js +220 -113
  3. package/dist/external-tracker.js +1225 -558
  4. package/dist/external-tracker.min.js +2 -2
  5. package/dist/external-tracker.min.js.map +4 -4
  6. package/dist/react/hooks/useApplePay.js +25 -36
  7. package/dist/react/hooks/usePaymentPolling.d.ts +9 -3
  8. package/dist/react/providers/TagadaProvider.js +5 -5
  9. package/dist/react/utils/money.d.ts +4 -3
  10. package/dist/react/utils/money.js +39 -6
  11. package/dist/react/utils/trackingUtils.js +1 -0
  12. package/dist/tagada-sdk.js +10142 -0
  13. package/dist/tagada-sdk.min.js +43 -0
  14. package/dist/tagada-sdk.min.js.map +7 -0
  15. package/dist/v2/core/client.js +34 -2
  16. package/dist/v2/core/config/environment.js +9 -2
  17. package/dist/v2/core/funnelClient.d.ts +180 -2
  18. package/dist/v2/core/funnelClient.js +289 -6
  19. package/dist/v2/core/resources/apiClient.js +1 -1
  20. package/dist/v2/core/resources/checkout.d.ts +68 -0
  21. package/dist/v2/core/resources/funnel.d.ts +25 -0
  22. package/dist/v2/core/resources/payments.d.ts +70 -3
  23. package/dist/v2/core/resources/payments.js +72 -7
  24. package/dist/v2/core/utils/index.d.ts +1 -0
  25. package/dist/v2/core/utils/index.js +2 -0
  26. package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
  27. package/dist/v2/core/utils/pluginConfig.js +68 -5
  28. package/dist/v2/core/utils/previewMode.d.ts +7 -0
  29. package/dist/v2/core/utils/previewMode.js +72 -14
  30. package/dist/v2/core/utils/previewModeIndicator.d.ts +19 -0
  31. package/dist/v2/core/utils/previewModeIndicator.js +414 -0
  32. package/dist/v2/core/utils/tokenStorage.d.ts +4 -0
  33. package/dist/v2/core/utils/tokenStorage.js +15 -1
  34. package/dist/v2/index.d.ts +9 -3
  35. package/dist/v2/index.js +8 -3
  36. package/dist/v2/react/components/ApplePayButton.d.ts +22 -123
  37. package/dist/v2/react/components/ApplePayButton.js +247 -317
  38. package/dist/v2/react/components/FunnelScriptInjector.d.ts +3 -1
  39. package/dist/v2/react/components/FunnelScriptInjector.js +255 -162
  40. package/dist/v2/react/components/GooglePayButton.d.ts +2 -0
  41. package/dist/v2/react/components/GooglePayButton.js +80 -64
  42. package/dist/v2/react/components/PreviewModeIndicator.d.ts +46 -0
  43. package/dist/v2/react/components/PreviewModeIndicator.js +113 -0
  44. package/dist/v2/react/hooks/useApplePayCheckout.d.ts +16 -0
  45. package/dist/v2/react/hooks/useApplePayCheckout.js +193 -0
  46. package/dist/v2/react/hooks/useFunnel.d.ts +48 -6
  47. package/dist/v2/react/hooks/useFunnel.js +25 -5
  48. package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +10 -0
  49. package/dist/v2/react/hooks/useGoogleAutocomplete.js +48 -0
  50. package/dist/v2/react/hooks/useGooglePayCheckout.d.ts +21 -0
  51. package/dist/v2/react/hooks/useGooglePayCheckout.js +198 -0
  52. package/dist/v2/react/hooks/usePaymentPolling.d.ts +15 -3
  53. package/dist/v2/react/hooks/usePaymentPolling.js +31 -9
  54. package/dist/v2/react/hooks/usePaymentQuery.d.ts +34 -2
  55. package/dist/v2/react/hooks/usePaymentQuery.js +731 -7
  56. package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +26 -0
  57. package/dist/v2/react/hooks/usePaymentRetrieve.js +175 -0
  58. package/dist/v2/react/hooks/usePixelTracking.d.ts +56 -0
  59. package/dist/v2/react/hooks/usePixelTracking.js +508 -0
  60. package/dist/v2/react/hooks/useStepConfig.d.ts +64 -0
  61. package/dist/v2/react/hooks/useStepConfig.js +53 -0
  62. package/dist/v2/react/index.d.ts +15 -5
  63. package/dist/v2/react/index.js +8 -2
  64. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +1 -0
  65. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +41 -13
  66. package/dist/v2/react/providers/TagadaProvider.js +24 -23
  67. package/dist/v2/standalone/external-tracker.d.ts +2 -0
  68. package/dist/v2/standalone/external-tracker.js +6 -3
  69. package/package.json +112 -112
  70. package/dist/v2/react/hooks/useApplePay.d.ts +0 -16
  71. package/dist/v2/react/hooks/useApplePay.js +0 -247
@@ -26,11 +26,79 @@ export interface CheckoutInitParams {
26
26
  locale?: string;
27
27
  };
28
28
  }
29
+ export interface UpsellTrigger {
30
+ id: string;
31
+ type: string;
32
+ productId: string | null;
33
+ }
34
+ export interface OrderBumpOfferVariant {
35
+ id: string;
36
+ name: string;
37
+ sku: string;
38
+ imageUrl: string;
39
+ active: boolean;
40
+ default: boolean;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ externalVariantId: string | null;
44
+ description: string;
45
+ currency: string | null;
46
+ }
47
+ export interface OrderBumpOfferProduct {
48
+ id: string;
49
+ name: string;
50
+ }
51
+ export interface PriceCurrencyOption {
52
+ rate: number;
53
+ amount: number;
54
+ lock: boolean;
55
+ date: string;
56
+ }
57
+ export interface OrderBumpOfferPrice {
58
+ id: string;
59
+ currencyOptions: Record<string, PriceCurrencyOption>;
60
+ }
61
+ export interface CheckoutOrderBumpOffer {
62
+ id: string;
63
+ type: string;
64
+ productId: string;
65
+ variantId: string;
66
+ priceId: string;
67
+ titleTrans: Record<string, string>;
68
+ descriptionTrans: Record<string, string>;
69
+ overrideImageUrl: string | null;
70
+ precheck: boolean;
71
+ displayPrice: boolean;
72
+ displayCompareAtPrice: boolean;
73
+ compareAtPriceDiscount: number;
74
+ quantity: number;
75
+ variant: OrderBumpOfferVariant;
76
+ product: OrderBumpOfferProduct;
77
+ price: OrderBumpOfferPrice;
78
+ }
79
+ export interface Upsell {
80
+ id: string;
81
+ type: string;
82
+ enabled: boolean;
83
+ triggers: UpsellTrigger[];
84
+ orderBumpOffers: CheckoutOrderBumpOffer[];
85
+ }
86
+ export interface Store {
87
+ id: string;
88
+ accountId: string;
89
+ name: string;
90
+ presentmentCurrencies: string[];
91
+ chargeCurrencies: string[];
92
+ upsells: Upsell[];
93
+ emailDomains: string[];
94
+ integrations: any[];
95
+ }
29
96
  export interface CheckoutSession {
30
97
  id: string;
31
98
  checkoutToken: string;
32
99
  status: string;
33
100
  storeId: string;
101
+ store: Store;
34
102
  accountId: string;
35
103
  customerId: string;
36
104
  draft: boolean;
@@ -470,6 +470,31 @@ export interface FunnelInitializeRequest {
470
470
  * When false, disables all funnel tracking events (useful for iframed previews in config editor)
471
471
  */
472
472
  funnelTracking?: boolean;
473
+ /**
474
+ * 🎯 Funnel environment override ('staging' | 'production')
475
+ * Determines which funnel config to use
476
+ */
477
+ funnelEnv?: 'staging' | 'production';
478
+ /**
479
+ * 🎯 Tagada client environment override ('production' | 'development' | 'local')
480
+ * Forces specific API environment
481
+ */
482
+ tagadaClientEnv?: 'production' | 'development' | 'local';
483
+ /**
484
+ * 🎯 Tagada client base URL override
485
+ * Forces custom API base URL (e.g., for local development with ngrok)
486
+ */
487
+ tagadaClientBaseUrl?: string;
488
+ /**
489
+ * 🌍 Display currency override (e.g., 'USD', 'EUR')
490
+ * Forces specific currency for display purposes
491
+ */
492
+ currency?: string;
493
+ /**
494
+ * 🌍 Display locale override (e.g., 'en', 'fr')
495
+ * Forces specific locale for display purposes
496
+ */
497
+ locale?: string;
473
498
  }
474
499
  export interface FunnelInitializeResponse {
475
500
  success: boolean;
@@ -7,14 +7,14 @@ export interface Payment {
7
7
  id: string;
8
8
  status: string;
9
9
  subStatus: string;
10
- requireAction: 'none' | 'redirect' | 'error';
10
+ requireAction: 'none' | 'redirect' | 'error' | 'radar';
11
11
  requireActionData?: {
12
- type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error';
12
+ type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error' | 'stripe_radar' | 'finix_radar' | 'radar';
13
13
  url?: string;
14
14
  processed: boolean;
15
15
  processorId?: string;
16
16
  metadata?: {
17
- type: 'redirect';
17
+ type: 'redirect' | 'stripe_radar' | 'finix_radar';
18
18
  redirect?: {
19
19
  redirectUrl: string;
20
20
  returnUrl: string;
@@ -25,12 +25,24 @@ export interface Payment {
25
25
  acsTransID: string;
26
26
  messageVersion: string;
27
27
  };
28
+ radar?: {
29
+ merchantId?: string;
30
+ environment?: 'sandbox' | 'live';
31
+ orderId?: string;
32
+ publishableKey?: string;
33
+ };
34
+ provider?: string;
35
+ isTest?: boolean;
28
36
  };
29
37
  redirectUrl?: string;
30
38
  resumeToken?: string;
31
39
  message?: string;
32
40
  errorCode?: string;
33
41
  };
42
+ order?: {
43
+ id: string;
44
+ checkoutSessionId: string;
45
+ };
34
46
  }
35
47
  export interface PaymentResponse {
36
48
  paymentId: string;
@@ -76,6 +88,12 @@ export interface PaymentOptions {
76
88
  threedsProvider?: 'basis_theory';
77
89
  initiatedBy?: 'customer' | 'merchant';
78
90
  source?: 'upsell' | 'checkout' | 'offer' | 'missing_club' | 'forced';
91
+ /**
92
+ * Override the store's default payment flow
93
+ * If not provided, the SDK will auto-read from stepConfig.paymentFlowId (if available)
94
+ * If neither is set, the store's selectedPaymentFlowId will be used
95
+ */
96
+ paymentFlowId?: string;
79
97
  /** @deprecated Use onPaymentSuccess instead - this will be removed in v3 */
80
98
  onSuccess?: (response: PaymentResponse) => void;
81
99
  /** @deprecated Use onPaymentFailed instead - this will be removed in v3 */
@@ -137,6 +155,11 @@ export declare class PaymentsResource {
137
155
  */
138
156
  createApplePayPaymentInstrument(basisTheory: any, // BasisTheory instance from @basis-theory/basis-theory-react
139
157
  applePayToken: ApplePayToken): Promise<PaymentInstrumentResponse>;
158
+ /**
159
+ * Create Google Pay payment instrument
160
+ */
161
+ createGooglePayPaymentInstrument(basisTheory: any, // BasisTheory instance from @basis-theory/basis-theory-react
162
+ googlePayToken: any): Promise<PaymentInstrumentResponse>;
140
163
  /**
141
164
  * Helper function to format expiry date
142
165
  */
@@ -147,6 +170,7 @@ export declare class PaymentsResource {
147
170
  processPaymentDirect(checkoutSessionId: string, paymentInstrumentId: string, threedsSessionId?: string, options?: {
148
171
  initiatedBy?: 'customer' | 'merchant';
149
172
  source?: 'upsell' | 'checkout' | 'offer' | 'missing_club' | 'forced';
173
+ paymentFlowId?: string;
150
174
  }): Promise<PaymentResponse>;
151
175
  /**
152
176
  * Get card payment instruments for customer
@@ -160,4 +184,47 @@ export declare class PaymentsResource {
160
184
  * Get payment status
161
185
  */
162
186
  getPaymentStatus(paymentId: string): Promise<Payment>;
187
+ /**
188
+ * Retrieve payment status from processor
189
+ * Used for external payment flows that require server-side status checks
190
+ */
191
+ retrievePayment(paymentId: string): Promise<{
192
+ retrieveResult?: {
193
+ status?: string;
194
+ message?: string;
195
+ success?: boolean;
196
+ };
197
+ paymentId: string;
198
+ transactionCreated?: boolean;
199
+ status?: string;
200
+ transactionId?: string;
201
+ message?: string;
202
+ success?: boolean;
203
+ error?: any;
204
+ }>;
205
+ saveRadarSession(data: {
206
+ orderId?: string;
207
+ checkoutSessionId?: string;
208
+ finixRadarSessionId?: string;
209
+ finixRadarSessionData?: Record<string, unknown>;
210
+ stripeRadarSessionId?: string;
211
+ stripeRadarSessionData?: Record<string, unknown>;
212
+ airwallexRadarSessionId?: string;
213
+ }): Promise<{
214
+ success: boolean;
215
+ radarSessionId: string;
216
+ }>;
217
+ /**
218
+ * Complete payment after an action (3DS, radar, etc.)
219
+ * This resumes the payment flow that was paused for additional authentication/verification
220
+ */
221
+ completePaymentAfterAction(paymentId: string): Promise<Payment>;
222
+ /**
223
+ * Update 3DS session status (used for Airwallex 3DS return handling)
224
+ */
225
+ updateThreedsStatus(data: {
226
+ paymentId: string;
227
+ status: 'succeeded' | 'failed' | 'pending';
228
+ paymentIntentId: string;
229
+ }): Promise<any>;
163
230
  }
@@ -78,6 +78,34 @@ export class PaymentsResource {
78
78
  const response = await this.apiClient.post('/api/v1/payment/create-payment-instrument', { paymentInstrumentData });
79
79
  return response;
80
80
  }
81
+ /**
82
+ * Create Google Pay payment instrument
83
+ */
84
+ async createGooglePayPaymentInstrument(basisTheory, // BasisTheory instance from @basis-theory/basis-theory-react
85
+ googlePayToken // Token from Basis Theory Google Pay tokenization
86
+ ) {
87
+ if (!basisTheory) {
88
+ throw new Error('Payment processor not initialized');
89
+ }
90
+ if (!googlePayToken.id) {
91
+ throw new Error('Google Pay token is missing');
92
+ }
93
+ const paymentInstrumentData = {
94
+ type: 'google_pay',
95
+ token: googlePayToken.id,
96
+ dpanType: googlePayToken.type,
97
+ card: {
98
+ bin: googlePayToken.card.bin,
99
+ last4: googlePayToken.card.last4,
100
+ expirationMonth: googlePayToken.card.expiration_month,
101
+ expirationYear: googlePayToken.card.expiration_year,
102
+ brand: googlePayToken.card.brand,
103
+ },
104
+ authMethod: googlePayToken?.details?.auth_method,
105
+ };
106
+ const response = await this.apiClient.post('/api/v1/payment/create-payment-instrument', { paymentInstrumentData });
107
+ return response;
108
+ }
81
109
  /**
82
110
  * Helper function to format expiry date
83
111
  */
@@ -95,13 +123,23 @@ export class PaymentsResource {
95
123
  * Process payment directly with checkout session
96
124
  */
97
125
  async processPaymentDirect(checkoutSessionId, paymentInstrumentId, threedsSessionId, options = {}) {
98
- return this.apiClient.post('/api/public/v1/checkout/pay-v2', {
99
- checkoutSessionId,
100
- paymentInstrumentId,
101
- ...(threedsSessionId && { threedsSessionId }),
102
- ...(options.initiatedBy && { initiatedBy: options.initiatedBy }),
103
- ...(options.source && { source: options.source }),
104
- });
126
+ console.log('[PaymentsResource] processPaymentDirect START', options.paymentFlowId ? `(flow: ${options.paymentFlowId})` : '');
127
+ try {
128
+ const response = await this.apiClient.post('/api/public/v1/checkout/pay-v2', {
129
+ checkoutSessionId,
130
+ paymentInstrumentId,
131
+ ...(threedsSessionId && { threedsSessionId }),
132
+ ...(options.initiatedBy && { initiatedBy: options.initiatedBy }),
133
+ ...(options.source && { source: options.source }),
134
+ ...(options.paymentFlowId && { paymentFlowId: options.paymentFlowId }),
135
+ });
136
+ console.log('[PaymentsResource] processPaymentDirect SUCCESS:', response);
137
+ return response;
138
+ }
139
+ catch (error) {
140
+ console.error('[PaymentsResource] processPaymentDirect ERROR:', error);
141
+ throw error;
142
+ }
105
143
  }
106
144
  /**
107
145
  * Get card payment instruments for customer
@@ -123,4 +161,31 @@ export class PaymentsResource {
123
161
  async getPaymentStatus(paymentId) {
124
162
  return this.apiClient.get(`/api/v1/payments/${paymentId}`);
125
163
  }
164
+ /**
165
+ * Retrieve payment status from processor
166
+ * Used for external payment flows that require server-side status checks
167
+ */
168
+ async retrievePayment(paymentId) {
169
+ return this.apiClient.post('/api/v1/payments/retrieve', {
170
+ paymentId,
171
+ });
172
+ }
173
+ async saveRadarSession(data) {
174
+ return this.apiClient.post('/api/v1/radar-sessions', data);
175
+ }
176
+ /**
177
+ * Complete payment after an action (3DS, radar, etc.)
178
+ * This resumes the payment flow that was paused for additional authentication/verification
179
+ */
180
+ async completePaymentAfterAction(paymentId) {
181
+ return this.apiClient.post('/api/v1/payments/complete-after-3ds', {
182
+ paymentId,
183
+ });
184
+ }
185
+ /**
186
+ * Update 3DS session status (used for Airwallex 3DS return handling)
187
+ */
188
+ async updateThreedsStatus(data) {
189
+ return this.apiClient.post('/api/v1/threeds/status', data);
190
+ }
126
191
  }
@@ -12,3 +12,4 @@ export * from './postPurchases';
12
12
  export * from './orderBump';
13
13
  export * from './sessionStorage';
14
14
  export * from './funnelQueryKeys';
15
+ export * from './configHotReload';
@@ -12,3 +12,5 @@ export * from './postPurchases';
12
12
  export * from './orderBump';
13
13
  export * from './sessionStorage';
14
14
  export * from './funnelQueryKeys';
15
+ // Config hot reload for live preview editing
16
+ export * from './configHotReload';
@@ -22,6 +22,14 @@ export type RawPluginConfig<TConfig = Record<string, any>> = {
22
22
  basePath?: string;
23
23
  config?: any;
24
24
  } & TConfig;
25
+ /**
26
+ * Synchronously get plugin config from meta tags
27
+ * This is a lightweight sync alternative to loadPluginConfig
28
+ * Use this when you need immediate config access (e.g., in CDN bundles)
29
+ *
30
+ * @returns Plugin config from meta tags or defaults
31
+ */
32
+ export declare function getPluginConfig(): PluginConfig;
25
33
  /**
26
34
  * Core plugin config loading function
27
35
  *
@@ -85,7 +85,10 @@ const loadLocalDevConfig = async (configVariant = 'default') => {
85
85
  };
86
86
  /**
87
87
  * Load static resources for local development
88
- * Loads /config/resources.static.json
88
+ *
89
+ * Priority:
90
+ * 1. /config/funnel.local.json (NEW - recommended)
91
+ * 2. /config/resources.static.json (OLD - deprecated, for backward compatibility)
89
92
  */
90
93
  const loadStaticResources = async () => {
91
94
  try {
@@ -99,15 +102,47 @@ const loadStaticResources = async () => {
99
102
  if (!isLocalEnvironment(true)) {
100
103
  return null;
101
104
  }
102
- // Load static resources file
103
- console.log('🛠️ [V2] Attempting to load /config/resources.static.json...');
105
+ // ============================================================
106
+ // PRIORITY 1: NEW format - funnel.local.json
107
+ // Also populates the stepConfig cache for getAssignedStepConfig()
108
+ // ============================================================
109
+ try {
110
+ console.log('🛠️ [V2] Attempting to load /config/funnel.local.json...');
111
+ const funnelResponse = await fetch('/config/funnel.local.json');
112
+ if (funnelResponse.ok) {
113
+ const funnelConfig = await funnelResponse.json();
114
+ console.log('🛠️ [V2] ✅ Loaded local funnel config (NEW format):', funnelConfig);
115
+ // Also trigger loadLocalFunnelConfig to populate the cache
116
+ // Import dynamically to avoid circular dependency
117
+ const { loadLocalFunnelConfig } = await import('../funnelClient');
118
+ await loadLocalFunnelConfig();
119
+ // Return staticResources in the old format for backward compatibility
120
+ // The new stepConfig system reads from funnel.local.json via getAssignedStepConfig()
121
+ if (funnelConfig.staticResources) {
122
+ // Transform flat format to old nested format for legacy compatibility
123
+ const transformed = {};
124
+ for (const [key, value] of Object.entries(funnelConfig.staticResources)) {
125
+ transformed[key] = { id: value };
126
+ }
127
+ return transformed;
128
+ }
129
+ return null;
130
+ }
131
+ }
132
+ catch (e) {
133
+ console.log('🛠️ [V2] funnel.local.json not found, trying legacy format...');
134
+ }
135
+ // ============================================================
136
+ // PRIORITY 2: OLD format - resources.static.json (deprecated)
137
+ // ============================================================
138
+ console.log('🛠️ [V2] Attempting to load /config/resources.static.json (legacy)...');
104
139
  const response = await fetch('/config/resources.static.json');
105
140
  if (!response.ok) {
106
- console.log('🛠️ [V2] resources.static.json not found or failed to load');
141
+ console.log('🛠️ [V2] No local static resources found');
107
142
  return null;
108
143
  }
109
144
  const staticResources = await response.json();
110
- console.log('🛠️ [V2] ✅ Loaded local static resources:', staticResources);
145
+ console.log('🛠️ [V2] ✅ Loaded legacy static resources:', staticResources);
111
146
  return staticResources;
112
147
  }
113
148
  catch (error) {
@@ -119,9 +154,37 @@ const loadStaticResources = async () => {
119
154
  * Helper to get content from meta tag
120
155
  */
121
156
  const getMetaContent = (name) => {
157
+ if (typeof document === 'undefined')
158
+ return undefined;
122
159
  const metaTag = document.querySelector(`meta[name="${name}"]`);
123
160
  return metaTag?.getAttribute('content') || undefined;
124
161
  };
162
+ /**
163
+ * Synchronously get plugin config from meta tags
164
+ * This is a lightweight sync alternative to loadPluginConfig
165
+ * Use this when you need immediate config access (e.g., in CDN bundles)
166
+ *
167
+ * @returns Plugin config from meta tags or defaults
168
+ */
169
+ export function getPluginConfig() {
170
+ if (typeof document === 'undefined') {
171
+ return { basePath: '/', config: {} };
172
+ }
173
+ const storeId = getMetaContent('x-plugin-store-id');
174
+ const accountId = getMetaContent('x-plugin-account-id');
175
+ const basePath = getMetaContent('x-plugin-base-path') || '/';
176
+ let config = {};
177
+ try {
178
+ const encodedConfig = getMetaContent('x-plugin-config');
179
+ if (encodedConfig) {
180
+ config = JSON.parse(decodeURIComponent(encodedConfig));
181
+ }
182
+ }
183
+ catch (error) {
184
+ console.warn('[TagadaSDK] Failed to parse plugin config from meta tag:', error);
185
+ }
186
+ return { storeId, accountId, basePath, config };
187
+ }
125
188
  /**
126
189
  * Load production config from meta tags (HIGHEST PRIORITY)
127
190
  * Meta tags are injected by the plugin middleware during HTML serving
@@ -42,10 +42,16 @@ export interface SDKOverrideParams {
42
42
  draft?: boolean;
43
43
  /** Enable/disable funnel tracking events (false in config editor iframe, true in funnel previews) */
44
44
  funnelTracking?: boolean;
45
+ /** Funnel environment (staging/production) - determines which funnel config to use */
46
+ funnelEnv?: 'staging' | 'production';
45
47
  /** Force specific environment (production/development/local) - overrides auto-detection */
46
48
  tagadaClientEnv?: 'production' | 'development' | 'local';
47
49
  /** Force custom API base URL - overrides environment-based URL */
48
50
  tagadaClientBaseUrl?: string;
51
+ /** Display currency override (e.g., 'USD', 'EUR') */
52
+ currency?: string;
53
+ /** Display locale override (e.g., 'en', 'fr') */
54
+ locale?: string;
49
55
  }
50
56
  /**
51
57
  * Check if force reset is active (simulates hard refresh)
@@ -68,6 +74,7 @@ export declare function getPreviewParams(): SDKOverrideParams;
68
74
  export declare function isDraftMode(): boolean;
69
75
  /**
70
76
  * Set draft mode in storage for persistence
77
+ * ⚠️ ONLY writes to localStorage (not cookies) to avoid resurrection issues
71
78
  */
72
79
  export declare function setDraftMode(draft: boolean): void;
73
80
  /**