@tagadapay/plugin-sdk 3.1.8 → 3.1.10

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 (50) hide show
  1. package/README.md +1129 -1129
  2. package/build-cdn.js +223 -113
  3. package/dist/external-tracker.js +135 -81
  4. package/dist/external-tracker.min.js +2 -2
  5. package/dist/external-tracker.min.js.map +4 -4
  6. package/dist/react/providers/TagadaProvider.js +5 -5
  7. package/dist/tagada-sdk.js +10164 -0
  8. package/dist/tagada-sdk.min.js +45 -0
  9. package/dist/tagada-sdk.min.js.map +7 -0
  10. package/dist/v2/core/funnelClient.d.ts +91 -4
  11. package/dist/v2/core/funnelClient.js +42 -3
  12. package/dist/v2/core/resources/funnel.d.ts +10 -0
  13. package/dist/v2/core/resources/payments.d.ts +21 -1
  14. package/dist/v2/core/resources/payments.js +34 -0
  15. package/dist/v2/core/utils/currency.d.ts +14 -0
  16. package/dist/v2/core/utils/currency.js +40 -0
  17. package/dist/v2/core/utils/index.d.ts +1 -0
  18. package/dist/v2/core/utils/index.js +2 -0
  19. package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
  20. package/dist/v2/core/utils/pluginConfig.js +28 -0
  21. package/dist/v2/core/utils/previewMode.d.ts +4 -0
  22. package/dist/v2/core/utils/previewMode.js +28 -0
  23. package/dist/v2/core/utils/previewModeIndicator.js +101 -101
  24. package/dist/v2/index.d.ts +7 -6
  25. package/dist/v2/index.js +6 -6
  26. package/dist/v2/react/components/ApplePayButton.d.ts +1 -2
  27. package/dist/v2/react/components/ApplePayButton.js +57 -58
  28. package/dist/v2/react/components/FunnelScriptInjector.js +161 -172
  29. package/dist/v2/react/components/GooglePayButton.d.ts +2 -0
  30. package/dist/v2/react/components/GooglePayButton.js +80 -64
  31. package/dist/v2/react/hooks/useFunnel.d.ts +8 -2
  32. package/dist/v2/react/hooks/useFunnel.js +2 -2
  33. package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +10 -0
  34. package/dist/v2/react/hooks/useGoogleAutocomplete.js +48 -0
  35. package/dist/v2/react/hooks/useGooglePayCheckout.d.ts +21 -0
  36. package/dist/v2/react/hooks/useGooglePayCheckout.js +198 -0
  37. package/dist/v2/react/hooks/usePaymentPolling.d.ts +7 -1
  38. package/dist/v2/react/hooks/usePaymentQuery.d.ts +2 -0
  39. package/dist/v2/react/hooks/usePaymentQuery.js +435 -8
  40. package/dist/v2/react/hooks/usePixelTracking.d.ts +56 -0
  41. package/dist/v2/react/hooks/usePixelTracking.js +508 -0
  42. package/dist/v2/react/hooks/useStepConfig.d.ts +8 -6
  43. package/dist/v2/react/hooks/useStepConfig.js +3 -2
  44. package/dist/v2/react/index.d.ts +6 -2
  45. package/dist/v2/react/index.js +3 -1
  46. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +1 -0
  47. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +33 -13
  48. package/dist/v2/react/providers/TagadaProvider.js +22 -21
  49. package/dist/v2/standalone/index.js +1 -1
  50. package/package.json +112 -112
@@ -1,9 +1,79 @@
1
1
  import { ApiClient } from './resources/apiClient';
2
- import { SimpleFunnelContext, FunnelAction, FunnelNavigationResult } from './resources/funnel';
2
+ import { FunnelAction, FunnelNavigationResult, SimpleFunnelContext } from './resources/funnel';
3
3
  import { PluginConfig } from './utils/pluginConfig';
4
+ /**
5
+ * Tracking providers supported by the SDK.
6
+ * Mirrors `TrackingType` in `apps/crm-app/.../types/tracking.ts`.
7
+ */
8
+ export declare enum TrackingProvider {
9
+ FACEBOOK = "facebook",
10
+ TIKTOK = "tiktok",
11
+ SNAPCHAT = "snapchat",
12
+ META_CONVERSION = "meta_conversion",
13
+ GTM = "gtm"
14
+ }
15
+ /**
16
+ * Base tracking config (all providers)
17
+ */
18
+ export interface BaseTrackingConfig {
19
+ enabled: boolean;
20
+ }
21
+ /**
22
+ * Pixel-based providers (Facebook, TikTok)
23
+ */
24
+ export interface PixelTrackingConfig extends BaseTrackingConfig {
25
+ pixelId: string;
26
+ events: {
27
+ PageView: boolean;
28
+ InitiateCheckout: boolean;
29
+ Purchase: boolean;
30
+ };
31
+ }
32
+ /**
33
+ * Snapchat pixel config (extends base pixel events)
34
+ */
35
+ export interface SnapchatTrackingConfig extends BaseTrackingConfig {
36
+ pixelId: string;
37
+ events: {
38
+ PageView: boolean;
39
+ InitiateCheckout: boolean;
40
+ Purchase: boolean;
41
+ AddToCart: boolean;
42
+ ViewContent: boolean;
43
+ Search: boolean;
44
+ AddToWishlist: boolean;
45
+ CompleteRegistration: boolean;
46
+ };
47
+ }
48
+ /**
49
+ * Meta Conversion API config
50
+ */
51
+ export interface MetaConversionTrackingConfig extends BaseTrackingConfig {
52
+ accessToken: string;
53
+ pixelId: string;
54
+ publishPurchaseIfNewCustomerOnly: boolean;
55
+ }
56
+ /**
57
+ * Google Tag Manager config
58
+ */
59
+ export interface GTMTrackingConfig extends BaseTrackingConfig {
60
+ containerId: string;
61
+ events: {
62
+ PageView: boolean;
63
+ InitiateCheckout: boolean;
64
+ Purchase: boolean;
65
+ AddToCart: boolean;
66
+ ViewContent: boolean;
67
+ };
68
+ }
69
+ /**
70
+ * Union of all tracking configs.
71
+ * This mirrors `TrackingFormValues` from the CRM.
72
+ */
73
+ export type PixelConfig = PixelTrackingConfig | SnapchatTrackingConfig | MetaConversionTrackingConfig | GTMTrackingConfig;
4
74
  /**
5
75
  * Runtime step configuration injected from the CRM
6
- * Contains payment flows, static resources, scripts, and pixel tracking configs
76
+ * Contains payment flows, static resources, scripts, and tracking configs
7
77
  */
8
78
  export interface RuntimeStepConfig {
9
79
  payment?: {
@@ -16,7 +86,13 @@ export interface RuntimeStepConfig {
16
86
  content: string;
17
87
  position?: 'head-start' | 'head-end' | 'body-start' | 'body-end';
18
88
  }>;
19
- pixels?: Record<string, string>;
89
+ pixels?: {
90
+ [TrackingProvider.FACEBOOK]?: PixelTrackingConfig[];
91
+ [TrackingProvider.TIKTOK]?: PixelTrackingConfig[];
92
+ [TrackingProvider.SNAPCHAT]?: SnapchatTrackingConfig[];
93
+ [TrackingProvider.META_CONVERSION]?: MetaConversionTrackingConfig[];
94
+ [TrackingProvider.GTM]?: GTMTrackingConfig[];
95
+ };
20
96
  }
21
97
  /**
22
98
  * Local funnel configuration for development
@@ -34,7 +110,7 @@ export interface LocalFunnelConfig {
34
110
  /** Custom scripts for local testing */
35
111
  scripts?: RuntimeStepConfig['scripts'];
36
112
  /** Pixel tracking config */
37
- pixels?: Record<string, string>;
113
+ pixels?: RuntimeStepConfig['pixels'];
38
114
  }
39
115
  /**
40
116
  * Load local funnel config from /config/funnel.local.json (for local dev only)
@@ -85,6 +161,17 @@ export declare function getAssignedStaticResources(): Record<string, string> | u
85
161
  * Returns only enabled scripts, filtered by position if specified
86
162
  */
87
163
  export declare function getAssignedScripts(position?: 'head-start' | 'head-end' | 'body-start' | 'body-end'): RuntimeStepConfig['scripts'];
164
+ /**
165
+ * Get assigned pixel tracking configuration (normalized to arrays)
166
+ * Always returns arrays of PixelConfig for consistent consumption.
167
+ */
168
+ export declare function getAssignedPixels(): {
169
+ [TrackingProvider.FACEBOOK]?: PixelTrackingConfig[];
170
+ [TrackingProvider.TIKTOK]?: PixelTrackingConfig[];
171
+ [TrackingProvider.SNAPCHAT]?: SnapchatTrackingConfig[];
172
+ [TrackingProvider.META_CONVERSION]?: MetaConversionTrackingConfig[];
173
+ [TrackingProvider.GTM]?: GTMTrackingConfig[];
174
+ } | undefined;
88
175
  export interface FunnelClientConfig {
89
176
  apiClient: ApiClient;
90
177
  debugMode?: boolean;
@@ -1,9 +1,21 @@
1
- import { FunnelResource, FunnelActionType } from './resources/funnel';
2
- import { EventDispatcher } from './utils/eventDispatcher';
3
- import { getFunnelSessionCookie, setFunnelSessionCookie } from './utils/sessionStorage';
4
1
  import { detectEnvironment } from './config/environment';
2
+ import { FunnelActionType, FunnelResource } from './resources/funnel';
3
+ import { EventDispatcher } from './utils/eventDispatcher';
5
4
  import { getSDKParams } from './utils/previewMode';
6
5
  import { injectPreviewModeIndicator } from './utils/previewModeIndicator';
6
+ import { getFunnelSessionCookie, setFunnelSessionCookie } from './utils/sessionStorage';
7
+ /**
8
+ * Tracking providers supported by the SDK.
9
+ * Mirrors `TrackingType` in `apps/crm-app/.../types/tracking.ts`.
10
+ */
11
+ export var TrackingProvider;
12
+ (function (TrackingProvider) {
13
+ TrackingProvider["FACEBOOK"] = "facebook";
14
+ TrackingProvider["TIKTOK"] = "tiktok";
15
+ TrackingProvider["SNAPCHAT"] = "snapchat";
16
+ TrackingProvider["META_CONVERSION"] = "meta_conversion";
17
+ TrackingProvider["GTM"] = "gtm";
18
+ })(TrackingProvider || (TrackingProvider = {}));
7
19
  /**
8
20
  * Get the funnel ID from the injected HTML
9
21
  * Returns undefined if not available
@@ -268,6 +280,31 @@ export function getAssignedScripts(position) {
268
280
  }
269
281
  return scripts.length > 0 ? scripts : undefined;
270
282
  }
283
+ /**
284
+ * Get assigned pixel tracking configuration (normalized to arrays)
285
+ * Always returns arrays of PixelConfig for consistent consumption.
286
+ */
287
+ export function getAssignedPixels() {
288
+ const stepConfig = getAssignedStepConfig();
289
+ const rawPixels = stepConfig?.pixels;
290
+ if (!rawPixels || typeof rawPixels !== 'object')
291
+ return undefined;
292
+ const normalized = {};
293
+ for (const [key, value] of Object.entries(rawPixels)) {
294
+ if (!value)
295
+ continue;
296
+ if (Array.isArray(value)) {
297
+ // Already an array
298
+ normalized[key] = value;
299
+ }
300
+ else if (typeof value === 'object') {
301
+ // Single object - wrap in array
302
+ normalized[key] = [value];
303
+ }
304
+ // Skip invalid entries
305
+ }
306
+ return Object.keys(normalized).length > 0 ? normalized : undefined;
307
+ }
271
308
  export class FunnelClient {
272
309
  constructor(config) {
273
310
  this.eventDispatcher = new EventDispatcher();
@@ -401,6 +438,8 @@ export class FunnelClient {
401
438
  funnelEnv: funnelEnv || undefined, // 🎯 Pass funnel environment (staging/production)
402
439
  tagadaClientEnv: sdkParams.tagadaClientEnv, // 🎯 Pass client environment override
403
440
  tagadaClientBaseUrl: sdkParams.tagadaClientBaseUrl, // 🎯 Pass custom API base URL
441
+ currency: sdkParams.currency, // 🌍 Pass display currency override
442
+ locale: sdkParams.locale, // 🌍 Pass display locale override
404
443
  });
405
444
  if (response.success && response.context) {
406
445
  const enriched = this.enrichContext(response.context);
@@ -485,6 +485,16 @@ export interface FunnelInitializeRequest {
485
485
  * Forces custom API base URL (e.g., for local development with ngrok)
486
486
  */
487
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;
488
498
  }
489
499
  export interface FunnelInitializeResponse {
490
500
  success: boolean;
@@ -9,7 +9,7 @@ export interface Payment {
9
9
  subStatus: string;
10
10
  requireAction: 'none' | 'redirect' | 'error' | 'radar';
11
11
  requireActionData?: {
12
- type: 'redirect' | 'threeds_auth' | 'processor_auth' | 'error' | 'stripe_radar' | 'finix_radar';
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;
@@ -31,12 +31,18 @@ export interface Payment {
31
31
  orderId?: string;
32
32
  publishableKey?: string;
33
33
  };
34
+ provider?: string;
35
+ isTest?: boolean;
34
36
  };
35
37
  redirectUrl?: string;
36
38
  resumeToken?: string;
37
39
  message?: string;
38
40
  errorCode?: string;
39
41
  };
42
+ order?: {
43
+ id: string;
44
+ checkoutSessionId: string;
45
+ };
40
46
  }
41
47
  export interface PaymentResponse {
42
48
  paymentId: string;
@@ -149,6 +155,11 @@ export declare class PaymentsResource {
149
155
  */
150
156
  createApplePayPaymentInstrument(basisTheory: any, // BasisTheory instance from @basis-theory/basis-theory-react
151
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>;
152
163
  /**
153
164
  * Helper function to format expiry date
154
165
  */
@@ -198,6 +209,7 @@ export declare class PaymentsResource {
198
209
  finixRadarSessionData?: Record<string, unknown>;
199
210
  stripeRadarSessionId?: string;
200
211
  stripeRadarSessionData?: Record<string, unknown>;
212
+ airwallexRadarSessionId?: string;
201
213
  }): Promise<{
202
214
  success: boolean;
203
215
  radarSessionId: string;
@@ -207,4 +219,12 @@ export declare class PaymentsResource {
207
219
  * This resumes the payment flow that was paused for additional authentication/verification
208
220
  */
209
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>;
210
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
  */
@@ -154,4 +182,10 @@ export class PaymentsResource {
154
182
  paymentId,
155
183
  });
156
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
+ }
157
191
  }
@@ -8,6 +8,20 @@ export interface Currency {
8
8
  name: string;
9
9
  decimalPlaces: number;
10
10
  }
11
+ /**
12
+ * Format money amount from minor units (cents) to a formatted string
13
+ *
14
+ * @param amountMinorUnits - Amount in minor units (e.g., 12345 for $123.45)
15
+ * @param currencyCode - ISO 4217 currency code (e.g., "USD", "EUR")
16
+ * @param locale - Locale for formatting (default: "en-US")
17
+ * @returns Formatted money string (e.g., "$123.45")
18
+ *
19
+ * @example
20
+ * formatMoney(12345, 'USD') // "$123.45"
21
+ * formatMoney(10000, 'EUR', 'de-DE') // "100,00 €"
22
+ * formatMoney(1000, 'JPY') // "¥1,000"
23
+ */
24
+ export declare function formatMoney(amountMinorUnits: number, currencyCode?: string, locale?: string): string;
11
25
  export declare class CurrencyUtils {
12
26
  /**
13
27
  * Get currency from context or fallback to default
@@ -2,6 +2,46 @@
2
2
  * Currency Utility Functions
3
3
  * Pure functions for currency management
4
4
  */
5
+ /**
6
+ * Format money amount from minor units (cents) to a formatted string
7
+ *
8
+ * @param amountMinorUnits - Amount in minor units (e.g., 12345 for $123.45)
9
+ * @param currencyCode - ISO 4217 currency code (e.g., "USD", "EUR")
10
+ * @param locale - Locale for formatting (default: "en-US")
11
+ * @returns Formatted money string (e.g., "$123.45")
12
+ *
13
+ * @example
14
+ * formatMoney(12345, 'USD') // "$123.45"
15
+ * formatMoney(10000, 'EUR', 'de-DE') // "100,00 €"
16
+ * formatMoney(1000, 'JPY') // "¥1,000"
17
+ */
18
+ export function formatMoney(amountMinorUnits, currencyCode = 'USD', locale = 'en-US') {
19
+ const decimalPlaces = CurrencyUtils.getDecimalPlaces(currencyCode);
20
+ // Convert minor units to major units
21
+ // Backend stores amounts with 2 decimal places for all currencies
22
+ // For currencies with 0 decimal places (JPY, KRW, etc.), divide by 100
23
+ let value;
24
+ if (decimalPlaces === 0) {
25
+ // For zero-decimal currencies, backend still stores with 2 decimals
26
+ value = amountMinorUnits / 100;
27
+ }
28
+ else {
29
+ value = amountMinorUnits / Math.pow(10, decimalPlaces);
30
+ }
31
+ try {
32
+ return new Intl.NumberFormat(locale, {
33
+ style: 'currency',
34
+ currency: currencyCode,
35
+ minimumFractionDigits: decimalPlaces,
36
+ maximumFractionDigits: decimalPlaces,
37
+ }).format(value);
38
+ }
39
+ catch {
40
+ // Fallback if Intl.NumberFormat fails
41
+ const symbol = CurrencyUtils.getCurrencySymbol(currencyCode);
42
+ return `${symbol}${value.toFixed(decimalPlaces)}`;
43
+ }
44
+ }
5
45
  export class CurrencyUtils {
6
46
  /**
7
47
  * Get currency from context or fallback to default
@@ -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
  *
@@ -154,9 +154,37 @@ const loadStaticResources = async () => {
154
154
  * Helper to get content from meta tag
155
155
  */
156
156
  const getMetaContent = (name) => {
157
+ if (typeof document === 'undefined')
158
+ return undefined;
157
159
  const metaTag = document.querySelector(`meta[name="${name}"]`);
158
160
  return metaTag?.getAttribute('content') || undefined;
159
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
+ }
160
188
  /**
161
189
  * Load production config from meta tags (HIGHEST PRIORITY)
162
190
  * Meta tags are injected by the plugin middleware during HTML serving
@@ -48,6 +48,10 @@ export interface SDKOverrideParams {
48
48
  tagadaClientEnv?: 'production' | 'development' | 'local';
49
49
  /** Force custom API base URL - overrides environment-based URL */
50
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;
51
55
  }
52
56
  /**
53
57
  * Check if force reset is active (simulates hard refresh)
@@ -34,6 +34,8 @@ const STORAGE_KEYS = {
34
34
  FORCE_RESET: 'tgd_force_reset',
35
35
  CLIENT_ENV: 'tgd_client_env',
36
36
  CLIENT_BASE_URL: 'tgd_client_base_url',
37
+ CURRENCY: 'tgd_currency',
38
+ LOCALE: 'tgd_locale',
37
39
  };
38
40
  /**
39
41
  * Check if force reset is active (simulates hard refresh)
@@ -173,6 +175,30 @@ export function getSDKParams() {
173
175
  tagadaClientBaseUrl = storageBaseUrl;
174
176
  }
175
177
  }
178
+ // Get display currency (URL > localStorage > cookie)
179
+ let currency;
180
+ const urlCurrency = urlParams.get('currency');
181
+ if (urlCurrency) {
182
+ currency = urlCurrency;
183
+ }
184
+ else {
185
+ const storageCurrency = getFromStorage(STORAGE_KEYS.CURRENCY) || getFromCookie(STORAGE_KEYS.CURRENCY);
186
+ if (storageCurrency) {
187
+ currency = storageCurrency;
188
+ }
189
+ }
190
+ // Get display locale (URL > localStorage > cookie)
191
+ let locale;
192
+ const urlLocale = urlParams.get('locale');
193
+ if (urlLocale) {
194
+ locale = urlLocale;
195
+ }
196
+ else {
197
+ const storageLocale = getFromStorage(STORAGE_KEYS.LOCALE) || getFromCookie(STORAGE_KEYS.LOCALE);
198
+ if (storageLocale) {
199
+ locale = storageLocale;
200
+ }
201
+ }
176
202
  return {
177
203
  forceReset,
178
204
  token,
@@ -183,6 +209,8 @@ export function getSDKParams() {
183
209
  funnelEnv,
184
210
  tagadaClientEnv,
185
211
  tagadaClientBaseUrl,
212
+ currency,
213
+ locale,
186
214
  };
187
215
  }
188
216
  /**