@tagadapay/plugin-sdk 3.1.12 → 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 (106) hide show
  1. package/build-cdn.js +129 -11
  2. package/dist/data/iso3166.d.ts +23 -33
  3. package/dist/data/iso3166.js +134 -198
  4. package/dist/data/languages.d.ts +5 -64
  5. package/dist/data/languages.js +23 -143
  6. package/dist/external-tracker.js +968 -101
  7. package/dist/external-tracker.min.js +2 -2
  8. package/dist/external-tracker.min.js.map +4 -4
  9. package/dist/react/hooks/useISOData.js +1 -1
  10. package/dist/react/hooks/usePaymentPolling.d.ts +3 -3
  11. package/dist/tagada-sdk.js +12066 -0
  12. package/dist/tagada-sdk.min.js +50 -0
  13. package/dist/tagada-sdk.min.js.map +7 -0
  14. package/dist/v2/core/client.d.ts +4 -2
  15. package/dist/v2/core/client.js +4 -3
  16. package/dist/v2/core/errors.d.ts +75 -0
  17. package/dist/v2/core/errors.js +104 -0
  18. package/dist/v2/core/funnelClient.d.ts +2 -0
  19. package/dist/v2/core/index.d.ts +1 -0
  20. package/dist/v2/core/index.js +2 -0
  21. package/dist/v2/core/pixelMapping.d.ts +49 -0
  22. package/dist/v2/core/pixelMapping.js +325 -0
  23. package/dist/v2/core/resources/apiClient.d.ts +2 -0
  24. package/dist/v2/core/resources/apiClient.js +52 -9
  25. package/dist/v2/core/resources/checkout.d.ts +89 -30
  26. package/dist/v2/core/resources/checkout.js +8 -0
  27. package/dist/v2/core/resources/customer.d.ts +20 -19
  28. package/dist/v2/core/resources/funnel.d.ts +17 -17
  29. package/dist/v2/core/resources/payments.d.ts +84 -13
  30. package/dist/v2/core/resources/payments.js +26 -9
  31. package/dist/v2/core/types.d.ts +50 -12
  32. package/dist/v2/core/types.js +0 -3
  33. package/dist/v2/core/utils/checkout.d.ts +2 -2
  34. package/dist/v2/core/utils/checkout.js +7 -2
  35. package/dist/v2/core/utils/currency.d.ts +14 -0
  36. package/dist/v2/core/utils/currency.js +40 -0
  37. package/dist/v2/core/utils/index.d.ts +1 -0
  38. package/dist/v2/core/utils/index.js +2 -0
  39. package/dist/v2/core/utils/order.d.ts +11 -9
  40. package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
  41. package/dist/v2/core/utils/pluginConfig.js +28 -0
  42. package/dist/v2/index.d.ts +3 -1
  43. package/dist/v2/index.js +1 -1
  44. package/dist/v2/react/components/FunnelScriptInjector.js +21 -0
  45. package/dist/v2/react/components/WhopCheckout.d.ts +24 -0
  46. package/dist/v2/react/components/WhopCheckout.js +231 -0
  47. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +1 -1
  48. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.d.ts +14 -0
  49. package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.js +181 -0
  50. package/dist/v2/react/hooks/payment-actions/useErrorAction.d.ts +9 -0
  51. package/dist/v2/react/hooks/payment-actions/useErrorAction.js +21 -0
  52. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.d.ts +14 -0
  53. package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.js +187 -0
  54. package/dist/v2/react/hooks/payment-actions/useKessPayAction.d.ts +11 -0
  55. package/dist/v2/react/hooks/payment-actions/useKessPayAction.js +91 -0
  56. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.d.ts +24 -0
  57. package/dist/v2/react/hooks/payment-actions/useMasterCardAction.js +221 -0
  58. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.d.ts +15 -0
  59. package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.js +142 -0
  60. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.d.ts +3 -0
  61. package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.js +13 -0
  62. package/dist/v2/react/hooks/payment-actions/useRedirectAction.d.ts +10 -0
  63. package/dist/v2/react/hooks/payment-actions/useRedirectAction.js +35 -0
  64. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.d.ts +14 -0
  65. package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.js +192 -0
  66. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.d.ts +14 -0
  67. package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.js +81 -0
  68. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.d.ts +11 -0
  69. package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.js +84 -0
  70. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.d.ts +14 -0
  71. package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.js +36 -0
  72. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.d.ts +31 -0
  73. package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.js +212 -0
  74. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.d.ts +14 -0
  75. package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.js +207 -0
  76. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.d.ts +12 -0
  77. package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.js +101 -0
  78. package/dist/v2/react/hooks/useCheckoutQuery.d.ts +6 -0
  79. package/dist/v2/react/hooks/useCheckoutQuery.js +45 -0
  80. package/dist/v2/react/hooks/useGeoLocation.d.ts +2 -1
  81. package/dist/v2/react/hooks/useGeoLocation.js +4 -2
  82. package/dist/v2/react/hooks/useISOData.js +1 -1
  83. package/dist/v2/react/hooks/usePaymentPolling.d.ts +3 -3
  84. package/dist/v2/react/hooks/usePaymentQuery.d.ts +18 -5
  85. package/dist/v2/react/hooks/usePaymentQuery.js +63 -1015
  86. package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +3 -2
  87. package/dist/v2/react/hooks/usePaymentRetrieve.js +3 -1
  88. package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -48
  89. package/dist/v2/react/hooks/usePixelTracking.js +212 -514
  90. package/dist/v2/react/hooks/useShippingRatesQuery.js +13 -5
  91. package/dist/v2/react/hooks/useWhopPaymentPolling.d.ts +30 -0
  92. package/dist/v2/react/hooks/useWhopPaymentPolling.js +61 -0
  93. package/dist/v2/react/index.d.ts +7 -0
  94. package/dist/v2/react/index.js +4 -0
  95. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +2 -1
  96. package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +3 -1
  97. package/dist/v2/react/providers/TagadaProvider.js +71 -2
  98. package/dist/v2/standalone/external-tracker.d.ts +52 -46
  99. package/dist/v2/standalone/external-tracker.js +205 -98
  100. package/dist/v2/standalone/index.d.ts +22 -0
  101. package/dist/v2/standalone/index.js +126 -1
  102. package/package.json +3 -3
  103. package/dist/react/utils/__tests__/urlUtils.test.d.ts +0 -1
  104. package/dist/react/utils/__tests__/urlUtils.test.js +0 -189
  105. package/dist/v2/core/__tests__/pathRemapping.test.d.ts +0 -11
  106. package/dist/v2/core/__tests__/pathRemapping.test.js +0 -776
@@ -29,7 +29,11 @@ export function useShippingRatesQuery(options = {}) {
29
29
  // Main shipping rates query
30
30
  const { data: shippingRatesData, isLoading: isFetching, error: fetchError, refetch: refetchRates, } = useQuery({
31
31
  queryKey: ['shipping-rates', effectiveSessionId],
32
- queryFn: () => shippingRatesResource.getShippingRates(effectiveSessionId),
32
+ queryFn: () => {
33
+ if (!enabled)
34
+ return Promise.resolve({ rates: [] });
35
+ return shippingRatesResource.getShippingRates(effectiveSessionId);
36
+ },
33
37
  enabled: enabled && !!effectiveSessionId,
34
38
  staleTime: 30000, // 30 seconds
35
39
  refetchOnWindowFocus: false,
@@ -76,8 +80,10 @@ export function useShippingRatesQuery(options = {}) {
76
80
  });
77
81
  // Select rate function
78
82
  const selectRate = useCallback(async (rateId) => {
83
+ if (!enabled)
84
+ return;
79
85
  await setShippingRateMutation.mutateAsync({ rateId });
80
- }, [setShippingRateMutation]);
86
+ }, [enabled, setShippingRateMutation]);
81
87
  // Auto-select cheapest rate when:
82
88
  // 1. Rates are loaded
83
89
  // 2. No rate is currently selected in checkout
@@ -117,8 +123,10 @@ export function useShippingRatesQuery(options = {}) {
117
123
  }, [shippingRates, checkoutSelectedRateId]);
118
124
  // Refetch function
119
125
  const refetch = useCallback(async () => {
126
+ if (!enabled)
127
+ return;
120
128
  await refetchRates();
121
- }, [refetchRates]);
129
+ }, [enabled, refetchRates]);
122
130
  // Clear error function
123
131
  const clearError = useCallback(() => {
124
132
  // TanStack Query doesn't provide a direct way to clear errors
@@ -127,7 +135,7 @@ export function useShippingRatesQuery(options = {}) {
127
135
  }, [refetch]);
128
136
  // Preview shipping rates for a country without updating session
129
137
  const previewRates = useCallback(async (countryCode, stateCode) => {
130
- if (!effectiveSessionId)
138
+ if (!enabled || !effectiveSessionId)
131
139
  return [];
132
140
  try {
133
141
  setIsPreviewLoading(true);
@@ -153,7 +161,7 @@ export function useShippingRatesQuery(options = {}) {
153
161
  finally {
154
162
  setIsPreviewLoading(false);
155
163
  }
156
- }, [effectiveSessionId, shippingRatesResource]);
164
+ }, [enabled, effectiveSessionId, shippingRatesResource]);
157
165
  return {
158
166
  shippingRates,
159
167
  selectedRate,
@@ -0,0 +1,30 @@
1
+ export interface WhopPayment {
2
+ id: string;
3
+ status: 'succeeded' | 'declined' | 'pending';
4
+ requireAction: 'none' | 'redirect' | 'error';
5
+ orderId: string;
6
+ amount: number;
7
+ currency: string;
8
+ order?: {
9
+ id: string;
10
+ amount: number;
11
+ currency: string;
12
+ };
13
+ }
14
+ export interface UseWhopPaymentPollingOptions {
15
+ apiService: {
16
+ fetch: <T>(url: string, options: any) => Promise<T>;
17
+ };
18
+ checkoutSessionId: string;
19
+ maxAttempts?: number;
20
+ intervalMs?: number;
21
+ onSuccess?: (payment: WhopPayment) => void;
22
+ onMaxAttemptsReached?: () => void;
23
+ onError?: (error: Error) => void;
24
+ }
25
+ export interface UseWhopPaymentPollingReturn {
26
+ startPolling: (receiptId: string, orderId: string) => void;
27
+ stopPolling: () => void;
28
+ isPolling: boolean;
29
+ }
30
+ export declare const useWhopPaymentPolling: ({ apiService, checkoutSessionId, maxAttempts, intervalMs, onSuccess, onMaxAttemptsReached, onError, }: UseWhopPaymentPollingOptions) => UseWhopPaymentPollingReturn;
@@ -0,0 +1,61 @@
1
+ import { useCallback, useEffect, useRef, useState } from 'react';
2
+ export const useWhopPaymentPolling = ({ apiService, checkoutSessionId, maxAttempts = 60, intervalMs = 2000, onSuccess, onMaxAttemptsReached, onError, }) => {
3
+ const pollIntervalRef = useRef(null);
4
+ const attemptsRef = useRef(0);
5
+ const currentParamsRef = useRef(null);
6
+ const [isPolling, setIsPolling] = useState(false);
7
+ const stopPolling = useCallback(() => {
8
+ if (pollIntervalRef.current) {
9
+ clearInterval(pollIntervalRef.current);
10
+ pollIntervalRef.current = null;
11
+ }
12
+ setIsPolling(false);
13
+ attemptsRef.current = 0;
14
+ currentParamsRef.current = null;
15
+ }, []);
16
+ const startPolling = useCallback((receiptId, orderId) => {
17
+ stopPolling();
18
+ attemptsRef.current = 0;
19
+ currentParamsRef.current = { receiptId, orderId };
20
+ setIsPolling(true);
21
+ pollIntervalRef.current = setInterval(async () => {
22
+ if (!currentParamsRef.current)
23
+ return;
24
+ try {
25
+ attemptsRef.current++;
26
+ console.log(`Whop payment polling attempt ${attemptsRef.current}/${maxAttempts}...`);
27
+ const data = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/whop-payment-status`, {
28
+ method: 'POST',
29
+ body: JSON.stringify(currentParamsRef.current),
30
+ headers: { 'Content-Type': 'application/json' },
31
+ });
32
+ if (data && (data.status === 'succeeded' || data.status === 'declined')) {
33
+ stopPolling();
34
+ onSuccess?.(data);
35
+ }
36
+ else if (attemptsRef.current >= maxAttempts) {
37
+ stopPolling();
38
+ onMaxAttemptsReached?.();
39
+ }
40
+ }
41
+ catch (error) {
42
+ console.warn(`Whop polling attempt ${attemptsRef.current} failed:`, error);
43
+ if (attemptsRef.current >= maxAttempts) {
44
+ stopPolling();
45
+ onError?.(error instanceof Error ? error : new Error(String(error)));
46
+ }
47
+ // Otherwise keep polling through transient errors
48
+ }
49
+ }, intervalMs);
50
+ }, [apiService, checkoutSessionId, maxAttempts, intervalMs, onSuccess, onMaxAttemptsReached, onError, stopPolling]);
51
+ useEffect(() => {
52
+ return () => {
53
+ stopPolling();
54
+ };
55
+ }, [stopPolling]);
56
+ return {
57
+ startPolling,
58
+ stopPolling,
59
+ isPolling,
60
+ };
61
+ };
@@ -8,6 +8,7 @@ export type { DebugScript } from './providers/TagadaProvider';
8
8
  export { ApplePayButton } from './components/ApplePayButton';
9
9
  export { GooglePayButton } from './components/GooglePayButton';
10
10
  export { PreviewModeIndicator } from './components/PreviewModeIndicator';
11
+ export { WhopCheckout } from './components/WhopCheckout';
11
12
  export { useApplePayCheckout } from './hooks/useApplePayCheckout';
12
13
  export { useAuth } from './hooks/useAuth';
13
14
  export { useCheckoutToken } from './hooks/useCheckoutToken';
@@ -46,6 +47,7 @@ export { useThreeds } from './hooks/useThreeds';
46
47
  export { useThreedsModal } from './hooks/useThreedsModal';
47
48
  export { useTranslation } from './hooks/useTranslation';
48
49
  export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
50
+ export { useWhopPaymentPolling } from './hooks/useWhopPaymentPolling';
49
51
  export { useFunnel } from './hooks/useFunnel';
50
52
  export { useStepConfig } from './hooks/useStepConfig';
51
53
  export { useFunnel as useFunnelLegacy, useSimpleFunnel } from './hooks/useFunnelLegacy';
@@ -63,6 +65,8 @@ export type { UseLoginOptions, UseLoginResult } from './hooks/useLogin';
63
65
  export type { ApplePayButtonProps } from './components/ApplePayButton';
64
66
  export type { GooglePayButtonProps } from './components/GooglePayButton';
65
67
  export type { PreviewModeIndicatorProps } from './components/PreviewModeIndicator';
68
+ export type { WhopCheckoutHandle, WhopCheckoutProps } from './components/WhopCheckout';
69
+ export type { WhopPayment, UseWhopPaymentPollingOptions, UseWhopPaymentPollingReturn } from './hooks/useWhopPaymentPolling';
66
70
  export type { GeoLocationData, UseGeoLocationOptions, UseGeoLocationReturn } from './hooks/useGeoLocation';
67
71
  export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
68
72
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
@@ -89,4 +93,7 @@ export type { UseStoreConfigQueryOptions as UseStoreConfigOptions, UseStoreConfi
89
93
  export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
90
94
  export type { UseVipOffersQueryOptions as UseVipOffersOptions, UseVipOffersQueryResult as UseVipOffersResult } from './hooks/useVipOffersQuery';
91
95
  export { formatMoney } from '../../react/utils/money';
96
+ export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
97
+ export type { TagadaErrorOptions, TagadaErrorCodeValue } from '../core/errors';
98
+ export type { Order, OrderItem as CoreOrderItem, OrderAddress, OrderSummary, OrderWithRelations, PaymentSummary, PromotionSummary, Subscription, DeviceInfo, PromotionCode, Customer, Store, PickupPoint, } from '../core/types';
92
99
  export type OrderItem = import('../core/utils/order').OrderLineItem;
@@ -9,6 +9,7 @@ export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
9
9
  export { ApplePayButton } from './components/ApplePayButton';
10
10
  export { GooglePayButton } from './components/GooglePayButton';
11
11
  export { PreviewModeIndicator } from './components/PreviewModeIndicator';
12
+ export { WhopCheckout } from './components/WhopCheckout';
12
13
  // Hooks
13
14
  export { useApplePayCheckout } from './hooks/useApplePayCheckout';
14
15
  export { useAuth } from './hooks/useAuth';
@@ -48,6 +49,7 @@ export { useThreeds } from './hooks/useThreeds';
48
49
  export { useThreedsModal } from './hooks/useThreedsModal';
49
50
  export { useTranslation } from './hooks/useTranslation';
50
51
  export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
52
+ export { useWhopPaymentPolling } from './hooks/useWhopPaymentPolling';
51
53
  // Funnel hooks
52
54
  export { useFunnel } from './hooks/useFunnel';
53
55
  // Step config hook (access runtime configuration from HTML injection)
@@ -58,3 +60,5 @@ export { useFunnel as useFunnelLegacy, useSimpleFunnel } from './hooks/useFunnel
58
60
  export { FunnelActionType } from '../core/resources/funnel';
59
61
  // Re-export utilities from main react
60
62
  export { formatMoney } from '../../react/utils/money';
63
+ // Error types
64
+ export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
@@ -3,6 +3,7 @@
3
3
  * Manages express payment methods (Apple Pay, Google Pay, PayPal, Klarna)
4
4
  */
5
5
  import React, { ReactNode } from 'react';
6
+ import { TagadaError } from '../../core/errors';
6
7
  import { CheckoutData } from '../../core/resources/checkout';
7
8
  import { Address, PaymentMethod } from '../../core/resources/expressPaymentMethods';
8
9
  type ExpressOrderLineItem = {
@@ -47,7 +48,7 @@ interface ExpressPaymentMethodsContextType {
47
48
  };
48
49
  }) => Promise<void>;
49
50
  loading?: boolean;
50
- error: string | null;
51
+ error: TagadaError | null;
51
52
  setError: (error: string | null) => void;
52
53
  }
53
54
  interface ExpressPaymentMethodsProviderProps {
@@ -5,6 +5,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
5
5
  */
6
6
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
7
7
  import { createContext, useCallback, useMemo, useState } from 'react';
8
+ import { TagadaError, TagadaErrorCode } from '../../core/errors';
8
9
  import { ExpressPaymentMethodsResource, } from '../../core/resources/expressPaymentMethods';
9
10
  import { getGlobalApiClient } from '../hooks/useApiQuery';
10
11
  import { useShippingRatesQuery } from '../hooks/useShippingRatesQuery';
@@ -170,6 +171,7 @@ export const ExpressPaymentMethodsProvider = ({ children, customerId, checkout,
170
171
  const paypalPaymentMethod = useMemo(() => paymentMethods?.find((p) => p.type === 'paypal'), [paymentMethods]);
171
172
  const klarnaPaymentMethod = useMemo(() => paymentMethods?.find((p) => p.type === 'klarna'), [paymentMethods]);
172
173
  const loading = !paymentMethods || isLoadingPaymentMethods;
174
+ const tagadaError = useMemo(() => error ? new TagadaError(error, { code: TagadaErrorCode.PAYMENT_FAILED }) : null, [error]);
173
175
  const contextValue = {
174
176
  paymentMethods,
175
177
  availableExpressPaymentMethodIds,
@@ -185,7 +187,7 @@ export const ExpressPaymentMethodsProvider = ({ children, customerId, checkout,
185
187
  handleAddExpressId,
186
188
  updateCheckoutSessionValues,
187
189
  updateCustomerEmail,
188
- error,
190
+ error: tagadaError,
189
191
  setError,
190
192
  };
191
193
  const hasAnyEnabled = Boolean(applePayPaymentMethod || googlePayPaymentMethod || paypalPaymentMethod || klarnaPaymentMethod);
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
4
4
  * TagadaProvider - Main provider component for the Tagada Pay React SDK
5
5
  */
6
6
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
7
- import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
7
+ import { Suspense, createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
8
8
  import { ApiService } from '../../../react/services/apiService';
9
9
  import { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from '../../../react/utils/money';
10
10
  import { TagadaClient } from '../../core/client';
@@ -213,6 +213,75 @@ export function TagadaProvider({ children, environment, customApiConfig, debugMo
213
213
  formatSimpleMoney,
214
214
  }), []);
215
215
  const [isDebugDrawerOpen, setIsDebugDrawerOpen] = useState(false);
216
+ // Track last injected script to prevent duplicate execution
217
+ /**
218
+ * Editor Element Click Bridge (Iframe → Parent)
219
+ *
220
+ * When running inside the CRM config editor iframe, elements can declare an `editor-id`
221
+ * attribute (e.g. <h1 editor-id="config.texts.checkoutTitle">Title</h1>).
222
+ *
223
+ * This effect sets up a delegated click listener on `document` that:
224
+ * - Finds the closest ancestor with an `editor-id`
225
+ * - Sends a `postMessage` to `window.parent` with the editorId and text content
226
+ *
227
+ * The parent (ConfigEditor) can then map this back to the corresponding config field.
228
+ */
229
+ useEffect(() => {
230
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
231
+ return;
232
+ }
233
+ const handleClick = (event) => {
234
+ if (!(event.target instanceof Element))
235
+ return;
236
+ const targetWithEditorId = event.target.closest('[editor-id]');
237
+ if (!targetWithEditorId)
238
+ return;
239
+ const editorId = targetWithEditorId.getAttribute('editor-id');
240
+ if (!editorId)
241
+ return;
242
+ const textContent = targetWithEditorId.textContent ?? '';
243
+ // Only attempt cross-window messaging when inside an iframe
244
+ const isInIframe = window.parent && window.parent !== window;
245
+ if (!isInIframe) {
246
+ return;
247
+ }
248
+ const message = {
249
+ type: 'TAGADAPAY_EDITOR_ELEMENT_CLICK',
250
+ editorId,
251
+ textContent,
252
+ };
253
+ try {
254
+ // Derive parent origin from document.referrer when possible; fall back to '*'
255
+ // This avoids postMessage origin mismatch errors in dev (e.g. 3001 ↔ 5173)
256
+ let targetOrigin = '*';
257
+ try {
258
+ if (typeof document !== 'undefined' && document.referrer) {
259
+ const url = new URL(document.referrer);
260
+ targetOrigin = url.origin;
261
+ }
262
+ }
263
+ catch {
264
+ // Fallback to '*'
265
+ targetOrigin = '*';
266
+ }
267
+ window.parent.postMessage(message, targetOrigin);
268
+ if (state.debugMode) {
269
+ // eslint-disable-next-line no-console
270
+ console.log('[TagadaProvider] Sent editor element click to parent:', message);
271
+ }
272
+ }
273
+ catch (error) {
274
+ if (state.debugMode) {
275
+ // eslint-disable-next-line no-console
276
+ console.error('[TagadaProvider] Failed to post editor element click message:', error);
277
+ }
278
+ }
279
+ };
280
+ document.addEventListener('click', handleClick, true);
281
+ return () => {
282
+ document.removeEventListener('click', handleClick, true);
283
+ };
284
+ }, [state.debugMode]);
216
285
  // Funnel Methods
217
286
  const funnelMethods = useMemo(() => {
218
287
  if (!client.funnel) {
@@ -335,7 +404,7 @@ export function TagadaProvider({ children, environment, customApiConfig, debugMo
335
404
  boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
336
405
  zIndex: 999997,
337
406
  transition: 'all 0.2s ease',
338
- }, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) })] })), canRenderChildren && children] }) }) }));
407
+ }, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(Suspense, { fallback: null, children: _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) }) })] })), canRenderChildren && children] }) }) }));
339
408
  }
340
409
  export function useTagadaContext() {
341
410
  const context = useContext(TagadaContext);
@@ -1,59 +1,48 @@
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 type { TagadaClient } from '../core/client';
25
+ export declare const TRACKER_VERSION = "1.0.0";
32
26
  export interface TagadaTrackerConfig {
33
27
  /** Store ID (required) */
34
28
  storeId: string;
35
- /** Account ID (required for session init) */
36
- accountId?: string;
37
- /** Funnel ID (optional - can be extracted from URL param) */
29
+ /** Account ID (required session init will fail without it) */
30
+ accountId: string;
31
+ /** Funnel ID (optional can be extracted from URL param) */
38
32
  funnelId?: string;
39
- /**
40
- * Step ID (REQUIRED for external pages)
41
- *
42
- * External URLs cannot be mapped to steps via URL matching (only works for Tagadapay-hosted pages).
43
- * You must explicitly specify which step this external page represents.
44
- */
33
+ /** Step ID (required for external pages — URL-to-step mapping only works for TagadaPay-hosted pages) */
45
34
  stepId: string;
46
- /** Step name (optional - for analytics/debugging) */
35
+ /** Step name (optional for analytics/debugging) */
47
36
  stepName?: string;
48
- /** Step type (optional - e.g., 'landing', 'offer', 'external') */
37
+ /** Step type (optional e.g., 'landing', 'offer', 'external') */
49
38
  stepType?: string;
50
- /** API base URL (defaults to production) */
39
+ /** API base URL (defaults to https://app.tagadapay.com) */
51
40
  apiBaseUrl?: string;
52
41
  /** Enable debug logging */
53
42
  debug?: boolean;
54
43
  /** Callback when session is ready */
55
44
  onReady?: (session: ExternalTrackerSession) => void;
56
- /** Callback on error */
45
+ /** Callback on error — when provided, init() will NOT throw */
57
46
  onError?: (error: Error) => void;
58
47
  }
59
48
  export interface ExternalTrackerSession {
@@ -71,49 +60,66 @@ export interface NavigateOptions {
71
60
  eventData?: Record<string, unknown>;
72
61
  /** Override return URL */
73
62
  returnUrl?: string;
74
- /** Disable auto-redirect to control navigation manually (default: true) */
63
+ /** Whether to auto-redirect after navigation (default: true) */
75
64
  autoRedirect?: boolean;
76
65
  }
66
+ export interface TrackEventOptions {
67
+ /** Event name (e.g., 'button_click', 'scroll_depth', 'video_play') */
68
+ name: string;
69
+ /** Arbitrary event data */
70
+ data?: Record<string, unknown>;
71
+ }
77
72
  declare class TagadaExternalTracker {
78
73
  private config;
79
74
  private client;
80
75
  private initialized;
81
76
  private initializing;
77
+ private unsubscribe;
78
+ /** Tracker version */
79
+ readonly version = "1.0.0";
82
80
  /**
83
- * Initialize the tracker using SDK infrastructure
81
+ * Initialize the tracker.
82
+ * When `onError` is provided, errors are passed to the callback and init()
83
+ * resolves to `null` instead of throwing.
84
84
  */
85
85
  init(config: TagadaTrackerConfig): Promise<ExternalTrackerSession | null>;
86
- /**
87
- * Get current session from SDK state
88
- */
86
+ /** Get current session data. */
89
87
  getSession(): ExternalTrackerSession | null;
90
- /**
91
- * Check if tracker is ready
92
- */
88
+ /** Whether the tracker is fully initialized and ready. */
93
89
  isReady(): boolean;
94
90
  /**
95
- * Navigate to next step in funnel using SDK's funnel client
91
+ * Navigate to the next step in the funnel.
92
+ * By default, auto-redirects the browser window.
96
93
  */
97
94
  navigate(options: NavigateOptions): Promise<{
98
95
  url: string;
99
96
  } | null>;
100
97
  /**
101
- * Get customer ID (for identifying the user)
98
+ * Track a custom event (e.g., button click, scroll depth, video play).
99
+ * Events are sent through the funnel orchestrator for unified analytics.
102
100
  */
101
+ trackEvent(options: TrackEventOptions): Promise<void>;
102
+ /** Get customer ID. */
103
103
  getCustomerId(): string | null;
104
- /**
105
- * Get funnel session ID
106
- */
104
+ /** Get funnel session ID. */
107
105
  getFunnelSessionId(): string | null;
108
106
  /**
109
- * Build a URL with funnel context parameters
110
- * Useful for linking to other external pages while preserving session
107
+ * Build a URL that preserves funnel session context.
108
+ * Use this to link to other external pages within the same funnel.
111
109
  */
112
110
  buildUrl(baseUrl: string, additionalParams?: Record<string, string>): string;
111
+ /** Get the underlying SDK client (advanced usage). */
112
+ getClient(): TagadaClient | null;
113
113
  /**
114
- * Get the underlying SDK client (for advanced usage)
114
+ * Reset the tracker to a new step without re-creating the session.
115
+ * Useful for SPAs that navigate between funnel steps client-side.
115
116
  */
116
- getClient(): TagadaClient | null;
117
+ reset(newStepId: string): Promise<ExternalTrackerSession | null>;
118
+ /**
119
+ * Destroy the tracker, clean up event listeners and state.
120
+ * Call this when the tracker is no longer needed (e.g., SPA teardown).
121
+ */
122
+ destroy(): void;
117
123
  private waitForClientReady;
118
124
  private initializeFunnel;
119
125
  }