@tagadapay/plugin-sdk 2.3.2 → 2.3.4

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.
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useCurrency } from '../hooks/useCurrency';
3
3
  import { useTagadaContext } from '../providers/TagadaProvider';
4
+ import { collectTrackingData } from '../utils/trackingUtils';
4
5
  import { usePluginConfig } from './usePluginConfig';
5
6
  export function useCheckout(options = {}) {
6
7
  const { apiService, updateCheckoutDebugData, refreshCoordinator, currency, isSessionInitialized } = useTagadaContext();
@@ -77,9 +78,13 @@ export function useCheckout(options = {}) {
77
78
  setIsLoading(true);
78
79
  setError(null);
79
80
  try {
80
- // Enhanced customerMetadata without tracking data
81
+ // Collect tracking data
82
+ const trackingData = await collectTrackingData();
83
+ // Enhanced customerMetadata with tracking data
81
84
  const enhancedCustomerMetadata = {
82
85
  ...params.customerMetadata,
86
+ localStorage: trackingData.localStorageData,
87
+ cookies: trackingData.trackingCookiesData,
83
88
  };
84
89
  const requestBody = {
85
90
  ...params,
@@ -0,0 +1,47 @@
1
+ export interface Discount {
2
+ id: string;
3
+ promotionId: string;
4
+ promotionCodeId: string | null;
5
+ appliedAt: string;
6
+ appliedManually: boolean;
7
+ promotion: {
8
+ id: string;
9
+ name: string;
10
+ };
11
+ }
12
+ export interface DiscountCodeValidation {
13
+ isValid: boolean;
14
+ code: string;
15
+ error?: string;
16
+ discount?: {
17
+ id: string;
18
+ name: string;
19
+ type: string;
20
+ value: number;
21
+ currency: string;
22
+ };
23
+ }
24
+ export interface UseDiscountsOptions {
25
+ checkoutSessionId?: string;
26
+ autoRefresh?: boolean;
27
+ }
28
+ export interface UseDiscountsResult {
29
+ appliedDiscounts: Discount[];
30
+ isLoading: boolean;
31
+ isApplying: boolean;
32
+ isRemoving: boolean;
33
+ error: Error | null;
34
+ applyDiscountCode: (code: string) => Promise<{
35
+ success: boolean;
36
+ error?: string;
37
+ discount?: Discount;
38
+ }>;
39
+ removeDiscountCode: (discountId: string) => Promise<{
40
+ success: boolean;
41
+ error?: string;
42
+ }>;
43
+ getAppliedDiscounts: () => Promise<Discount[]>;
44
+ refresh: () => Promise<void>;
45
+ clearError: () => void;
46
+ }
47
+ export declare function useDiscounts(options?: UseDiscountsOptions): UseDiscountsResult;
@@ -0,0 +1,163 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useTagadaContext } from '../providers/TagadaProvider';
3
+ export function useDiscounts(options = {}) {
4
+ const { apiService, refreshCoordinator } = useTagadaContext();
5
+ const { checkoutSessionId, autoRefresh = true } = options;
6
+ const [appliedDiscounts, setAppliedDiscounts] = useState([]);
7
+ const [isLoading, setIsLoading] = useState(false);
8
+ const [isApplying, setIsApplying] = useState(false);
9
+ const [isRemoving, setIsRemoving] = useState(false);
10
+ const [error, setError] = useState(null);
11
+ const clearError = useCallback(() => {
12
+ setError(null);
13
+ }, []);
14
+ const getAppliedDiscounts = useCallback(async () => {
15
+ if (!checkoutSessionId) {
16
+ throw new Error('No checkout session available');
17
+ }
18
+ setIsLoading(true);
19
+ setError(null);
20
+ try {
21
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions`, {
22
+ method: 'GET',
23
+ });
24
+ setAppliedDiscounts(response);
25
+ return response;
26
+ }
27
+ catch (err) {
28
+ const error = err instanceof Error ? err : new Error('Failed to fetch applied discounts');
29
+ setError(error);
30
+ console.error('Failed to fetch applied discounts:', error);
31
+ throw error;
32
+ }
33
+ finally {
34
+ setIsLoading(false);
35
+ }
36
+ }, [checkoutSessionId, apiService]);
37
+ const applyDiscountCode = useCallback(async (code) => {
38
+ if (!checkoutSessionId) {
39
+ return { success: false, error: 'No checkout session available' };
40
+ }
41
+ if (!code || code.trim() === '') {
42
+ return { success: false, error: 'Discount code is required' };
43
+ }
44
+ setIsApplying(true);
45
+ setError(null);
46
+ try {
47
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions/apply`, {
48
+ method: 'POST',
49
+ body: { code: code.trim() },
50
+ });
51
+ if (response.success) {
52
+ // Refresh the applied discounts list
53
+ await getAppliedDiscounts();
54
+ // Trigger a refresh of the checkout session
55
+ refreshCoordinator?.notifyCheckoutChanged();
56
+ return { success: true, discount: response.promotion };
57
+ }
58
+ else {
59
+ return { success: false, error: response.error?.message || 'Failed to apply discount code' };
60
+ }
61
+ }
62
+ catch (err) {
63
+ const error = err instanceof Error ? err : new Error('Failed to apply discount code');
64
+ setError(error);
65
+ console.error('Failed to apply discount code:', error);
66
+ // Try to extract error message from API response
67
+ let errorMessage = 'Failed to apply discount code';
68
+ if (err && typeof err === 'object' && 'response' in err) {
69
+ const apiError = err;
70
+ if (apiError.response?.data?.error?.message) {
71
+ errorMessage = apiError.response.data.error.message;
72
+ }
73
+ else if (apiError.response?.data?.message) {
74
+ errorMessage = apiError.response.data.message;
75
+ }
76
+ }
77
+ return { success: false, error: errorMessage };
78
+ }
79
+ finally {
80
+ setIsApplying(false);
81
+ }
82
+ }, [checkoutSessionId, apiService, getAppliedDiscounts, refreshCoordinator]);
83
+ const removeDiscountCode = useCallback(async (discountId) => {
84
+ if (!checkoutSessionId) {
85
+ return { success: false, error: 'No checkout session available' };
86
+ }
87
+ if (!discountId) {
88
+ return { success: false, error: 'Discount ID is required' };
89
+ }
90
+ setIsRemoving(true);
91
+ setError(null);
92
+ try {
93
+ const response = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/promotions/${discountId}`, {
94
+ method: 'DELETE',
95
+ });
96
+ if (response.success) {
97
+ // Refresh the applied discounts list
98
+ await getAppliedDiscounts();
99
+ // Trigger a refresh of the checkout session
100
+ refreshCoordinator?.notifyCheckoutChanged();
101
+ return { success: true };
102
+ }
103
+ else {
104
+ return { success: false, error: response.error?.message || 'Failed to remove discount' };
105
+ }
106
+ }
107
+ catch (err) {
108
+ const error = err instanceof Error ? err : new Error('Failed to remove discount');
109
+ setError(error);
110
+ console.error('Failed to remove discount:', error);
111
+ // Try to extract error message from API response
112
+ let errorMessage = 'Failed to remove discount';
113
+ if (err && typeof err === 'object' && 'response' in err) {
114
+ const apiError = err;
115
+ if (apiError.response?.data?.error?.message) {
116
+ errorMessage = apiError.response.data.error.message;
117
+ }
118
+ else if (apiError.response?.data?.message) {
119
+ errorMessage = apiError.response.data.message;
120
+ }
121
+ }
122
+ return { success: false, error: errorMessage };
123
+ }
124
+ finally {
125
+ setIsRemoving(false);
126
+ }
127
+ }, [checkoutSessionId, apiService, getAppliedDiscounts, refreshCoordinator]);
128
+ const refresh = useCallback(async () => {
129
+ if (checkoutSessionId) {
130
+ await getAppliedDiscounts();
131
+ }
132
+ }, [checkoutSessionId, getAppliedDiscounts]);
133
+ // Auto-refresh when checkout session changes
134
+ useEffect(() => {
135
+ if (autoRefresh && checkoutSessionId) {
136
+ getAppliedDiscounts();
137
+ }
138
+ }, [checkoutSessionId, autoRefresh, getAppliedDiscounts]);
139
+ // Listen for checkout session refreshes
140
+ useEffect(() => {
141
+ if (!autoRefresh || !checkoutSessionId)
142
+ return;
143
+ const handleRefresh = async () => {
144
+ await getAppliedDiscounts();
145
+ };
146
+ refreshCoordinator?.registerCheckoutRefresh(handleRefresh);
147
+ return () => refreshCoordinator?.unregisterCheckoutRefresh();
148
+ }, [checkoutSessionId, autoRefresh, getAppliedDiscounts, refreshCoordinator]);
149
+ return {
150
+ // State
151
+ appliedDiscounts,
152
+ isLoading,
153
+ isApplying,
154
+ isRemoving,
155
+ error,
156
+ // Actions
157
+ applyDiscountCode,
158
+ removeDiscountCode,
159
+ getAppliedDiscounts,
160
+ refresh,
161
+ clearError,
162
+ };
163
+ }
@@ -14,6 +14,7 @@ export interface ProductPrice {
14
14
  export interface ProductVariant {
15
15
  id: string;
16
16
  name: string;
17
+ description: string;
17
18
  sku?: string;
18
19
  weight?: number;
19
20
  imageUrl?: string;
@@ -6,6 +6,7 @@ export { useAuth } from './hooks/useAuth';
6
6
  export { useCheckout } from './hooks/useCheckout';
7
7
  export { useCurrency } from './hooks/useCurrency';
8
8
  export { useCustomer } from './hooks/useCustomer';
9
+ export { useDiscounts } from './hooks/useDiscounts';
9
10
  export { useEnvironment } from './hooks/useEnvironment';
10
11
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
11
12
  export { useLocale } from './hooks/useLocale';
@@ -16,22 +17,23 @@ export { usePostPurchases } from './hooks/usePostPurchases';
16
17
  export { useProducts } from './hooks/useProducts';
17
18
  export { useSession } from './hooks/useSession';
18
19
  export { useTagadaContext } from './providers/TagadaProvider';
19
- export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
20
+ export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
20
21
  export type { PluginConfig } from './hooks/usePluginConfig';
21
- export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
22
+ export { getAvailableLanguages, useCountryOptions, useISOData, useRegionOptions } from './hooks/useISOData';
22
23
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
23
- export type { GooglePrediction, GoogleAddressComponent, GooglePlaceDetails, ExtractedAddress, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
24
+ export type { ExtractedAddress, GoogleAddressComponent, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
24
25
  export { useOrder } from './hooks/useOrder';
25
26
  export type { UseOrderOptions, UseOrderResult } from './hooks/useOrder';
26
27
  export { usePayment } from './hooks/usePayment';
27
28
  export { usePaymentPolling } from './hooks/usePaymentPolling';
28
29
  export { useThreeds } from './hooks/useThreeds';
29
30
  export { useThreedsModal } from './hooks/useThreedsModal';
30
- export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Order, OrderAddress, OrderItem, OrderSummary, PickupPoint, Session, Store, } from './types';
31
- export type { CheckoutSessionPreview, CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, Promotion, UseCheckoutOptions, UseCheckoutResult, } from './hooks/useCheckout';
31
+ export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Order, OrderAddress, OrderItem, OrderSummary, PickupPoint, Session, Store } from './types';
32
+ export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutSessionPreview, Promotion, UseCheckoutOptions, UseCheckoutResult } from './hooks/useCheckout';
33
+ export type { Discount, DiscountCodeValidation, UseDiscountsOptions, UseDiscountsResult } from './hooks/useDiscounts';
32
34
  export type { OrderBumpPreview, UseOrderBumpOptions, UseOrderBumpResult } from './hooks/useOrderBump';
33
- export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult, } from './hooks/usePostPurchases';
35
+ export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult } from './hooks/usePostPurchases';
34
36
  export type { Payment, PaymentPollingHook, PollingOptions } from './hooks/usePaymentPolling';
35
- export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession, } from './hooks/useThreeds';
36
- export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse, } from './hooks/usePayment';
37
- export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from './utils/money';
37
+ export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
38
+ export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse } from './hooks/usePayment';
39
+ export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -9,6 +9,7 @@ export { useAuth } from './hooks/useAuth';
9
9
  export { useCheckout } from './hooks/useCheckout';
10
10
  export { useCurrency } from './hooks/useCurrency';
11
11
  export { useCustomer } from './hooks/useCustomer';
12
+ export { useDiscounts } from './hooks/useDiscounts';
12
13
  export { useEnvironment } from './hooks/useEnvironment';
13
14
  export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
14
15
  export { useLocale } from './hooks/useLocale';
@@ -20,9 +21,9 @@ export { useProducts } from './hooks/useProducts';
20
21
  export { useSession } from './hooks/useSession';
21
22
  export { useTagadaContext } from './providers/TagadaProvider';
22
23
  // Plugin configuration hooks
23
- export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
24
+ export { clearPluginConfigCache, debugPluginConfig, getPluginConfig, useBasePath, usePluginConfig } from './hooks/usePluginConfig';
24
25
  // ISO Data hooks
25
- export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
26
+ export { getAvailableLanguages, useCountryOptions, useISOData, useRegionOptions } from './hooks/useISOData';
26
27
  // Order hook exports
27
28
  export { useOrder } from './hooks/useOrder';
28
29
  // Payment hooks exports
@@ -33,4 +34,4 @@ export { useThreedsModal } from './hooks/useThreedsModal';
33
34
  // Component exports (if any)
34
35
  // export { SomeComponent } from './components/SomeComponent';
35
36
  // Utility exports
36
- export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from './utils/money';
37
+ export { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from './utils/money';
@@ -38,11 +38,11 @@ const InitializationLoader = () => (_jsxs("div", { style: {
38
38
  borderTop: '1.5px solid #9ca3af',
39
39
  borderRadius: '50%',
40
40
  animation: 'tagada-spin 1s linear infinite',
41
- } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
42
- @keyframes tagada-spin {
43
- 0% { transform: rotate(0deg); }
44
- 100% { transform: rotate(360deg); }
45
- }
41
+ } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
42
+ @keyframes tagada-spin {
43
+ 0% { transform: rotate(0deg); }
44
+ 100% { transform: rotate(360deg); }
45
+ }
46
46
  ` })] }));
47
47
  const TagadaContext = createContext(null);
48
48
  export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
@@ -0,0 +1,24 @@
1
+ export interface TrackingData {
2
+ trackingCookiesData: Record<string, string>;
3
+ localStorageData: Record<string, string>;
4
+ }
5
+ /**
6
+ * Define pixel tracking cookie patterns for various platforms
7
+ */
8
+ export declare const trackingCookiePatterns: RegExp[];
9
+ /**
10
+ * Function to get cookies with retry logic
11
+ */
12
+ export declare const getCookiesWithRetry: (maxRetries?: number, delay?: number) => Promise<string[]>;
13
+ /**
14
+ * Collect localStorage data as dictionary
15
+ */
16
+ export declare const getLocalStorageData: () => Record<string, string>;
17
+ /**
18
+ * Collect tracking cookies data based on defined patterns
19
+ */
20
+ export declare const getTrackingCookiesData: () => Promise<Record<string, string>>;
21
+ /**
22
+ * Collect all tracking data (localStorage and cookies)
23
+ */
24
+ export declare const collectTrackingData: () => Promise<TrackingData>;
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Define pixel tracking cookie patterns for various platforms
3
+ */
4
+ export const trackingCookiePatterns = [
5
+ // Meta/Facebook pixels
6
+ /^_fbp/,
7
+ /^_fbc/,
8
+ /^fr$/,
9
+ /^_fbq/,
10
+ /^fbq/,
11
+ /^sb$/,
12
+ // Google Analytics & Ads
13
+ /^_ga/,
14
+ /^_gid/,
15
+ /^_gcl_au/,
16
+ /^_gac_/,
17
+ /^_gtag/,
18
+ /^_gat/,
19
+ /^_dc_gtm_/,
20
+ /^_gtm/,
21
+ // Google Ads
22
+ /^_gcl_/,
23
+ /^_gclid/,
24
+ /^_gclsrc/,
25
+ // Snapchat
26
+ /^_scid/,
27
+ /^_sctr/,
28
+ /^_schn/,
29
+ /^_scpx/,
30
+ // TikTok
31
+ /^_ttp/,
32
+ /^_tt_enable_cookie/,
33
+ /^_ttclid/,
34
+ /^_tta/,
35
+ // Pinterest
36
+ /^_pin/,
37
+ /^_pinterest_/,
38
+ /^_pinid/,
39
+ // Twitter/X
40
+ /^_twitter/,
41
+ /^_twid/,
42
+ /^muc_ads/,
43
+ // LinkedIn
44
+ /^_li/,
45
+ /^AnalyticsSyncHistory/,
46
+ /^bcookie/,
47
+ /^bscookie/,
48
+ // Microsoft/Bing
49
+ /^_uetsid/,
50
+ /^_uetvid/,
51
+ /^MUID/,
52
+ /^_msdcs/,
53
+ // Amazon
54
+ /^ad-id/,
55
+ /^ad-privacy/,
56
+ // CVG tracking
57
+ /^__cvg_uid/,
58
+ /^__cvg_sid/,
59
+ /^__cvg_session/,
60
+ // Shopify tracking
61
+ /^_shopify_y/,
62
+ /^_shopify_s/,
63
+ /^_shopify_ga/,
64
+ /^_shopify_ga_/,
65
+ /^_shopify_sa_p/,
66
+ /^_shopify_sa_t/,
67
+ // General tracking
68
+ /^_awc/,
69
+ /^_aw_/,
70
+ /^utm_/,
71
+ /^_clck/,
72
+ /^_clsk/,
73
+ ];
74
+ /**
75
+ * Function to get cookies with retry logic
76
+ */
77
+ export const getCookiesWithRetry = async (maxRetries = 3, delay = 100) => {
78
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
79
+ try {
80
+ const cookies = document.cookie.split('; ');
81
+ if (cookies.length > 0 && cookies[0] !== '') {
82
+ return cookies;
83
+ }
84
+ // If no cookies found, wait and retry
85
+ if (attempt < maxRetries) {
86
+ console.log(`Cookie collection attempt ${attempt} failed, retrying in ${delay}ms...`);
87
+ await new Promise((resolve) => setTimeout(resolve, delay));
88
+ }
89
+ }
90
+ catch (error) {
91
+ console.warn(`Cookie collection attempt ${attempt} failed:`, error);
92
+ if (attempt < maxRetries) {
93
+ await new Promise((resolve) => setTimeout(resolve, delay));
94
+ }
95
+ }
96
+ }
97
+ return [];
98
+ };
99
+ /**
100
+ * Collect localStorage data as dictionary
101
+ */
102
+ export const getLocalStorageData = () => {
103
+ const localStorageData = {};
104
+ try {
105
+ for (let i = 0; i < localStorage.length; i++) {
106
+ const key = localStorage.key(i);
107
+ if (key) {
108
+ localStorageData[key] = localStorage.getItem(key) || '';
109
+ }
110
+ }
111
+ }
112
+ catch (error) {
113
+ console.warn('Failed to read localStorage:', error);
114
+ }
115
+ return localStorageData;
116
+ };
117
+ /**
118
+ * Collect tracking cookies data based on defined patterns
119
+ */
120
+ export const getTrackingCookiesData = async () => {
121
+ const trackingCookiesData = {};
122
+ try {
123
+ // Get cookies with retry logic
124
+ const cookies = await getCookiesWithRetry();
125
+ if (cookies.length === 0) {
126
+ console.warn('No cookies found after retry attempts');
127
+ }
128
+ else {
129
+ console.log(`Successfully collected ${cookies.length} cookies`);
130
+ }
131
+ cookies.forEach((cookie) => {
132
+ const [key, ...valueParts] = cookie.split('=');
133
+ const value = valueParts.join('='); // Handle values that might contain =
134
+ if (key && trackingCookiePatterns.some((pattern) => pattern.test(key))) {
135
+ try {
136
+ trackingCookiesData[key] = decodeURIComponent(value || '');
137
+ }
138
+ catch (error) {
139
+ // If decoding fails, use raw value
140
+ trackingCookiesData[key] = value || '';
141
+ }
142
+ }
143
+ });
144
+ // Log specific cookies we're looking for
145
+ const importantCookies = ['_shopify_y', '__cvg_uid', '_fbp', '_ga'];
146
+ importantCookies.forEach((cookieName) => {
147
+ if (trackingCookiesData[cookieName]) {
148
+ console.log(`Found ${cookieName}:`, trackingCookiesData[cookieName]);
149
+ }
150
+ else {
151
+ console.log(`Missing ${cookieName} cookie`);
152
+ }
153
+ });
154
+ }
155
+ catch (error) {
156
+ console.warn('Failed to read tracking cookies:', error);
157
+ }
158
+ return trackingCookiesData;
159
+ };
160
+ /**
161
+ * Collect all tracking data (localStorage and cookies)
162
+ */
163
+ export const collectTrackingData = async () => {
164
+ const [localStorageData, trackingCookiesData] = await Promise.all([
165
+ Promise.resolve(getLocalStorageData()),
166
+ getTrackingCookiesData(),
167
+ ]);
168
+ return {
169
+ localStorageData,
170
+ trackingCookiesData,
171
+ };
172
+ };