@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.
- package/build-cdn.js +129 -11
- package/dist/data/iso3166.d.ts +23 -33
- package/dist/data/iso3166.js +134 -198
- package/dist/data/languages.d.ts +5 -64
- package/dist/data/languages.js +23 -143
- package/dist/external-tracker.js +968 -101
- package/dist/external-tracker.min.js +2 -2
- package/dist/external-tracker.min.js.map +4 -4
- package/dist/react/hooks/useISOData.js +1 -1
- package/dist/react/hooks/usePaymentPolling.d.ts +3 -3
- package/dist/tagada-sdk.js +12066 -0
- package/dist/tagada-sdk.min.js +50 -0
- package/dist/tagada-sdk.min.js.map +7 -0
- package/dist/v2/core/client.d.ts +4 -2
- package/dist/v2/core/client.js +4 -3
- package/dist/v2/core/errors.d.ts +75 -0
- package/dist/v2/core/errors.js +104 -0
- package/dist/v2/core/funnelClient.d.ts +2 -0
- package/dist/v2/core/index.d.ts +1 -0
- package/dist/v2/core/index.js +2 -0
- package/dist/v2/core/pixelMapping.d.ts +49 -0
- package/dist/v2/core/pixelMapping.js +325 -0
- package/dist/v2/core/resources/apiClient.d.ts +2 -0
- package/dist/v2/core/resources/apiClient.js +52 -9
- package/dist/v2/core/resources/checkout.d.ts +89 -30
- package/dist/v2/core/resources/checkout.js +8 -0
- package/dist/v2/core/resources/customer.d.ts +20 -19
- package/dist/v2/core/resources/funnel.d.ts +17 -17
- package/dist/v2/core/resources/payments.d.ts +84 -13
- package/dist/v2/core/resources/payments.js +26 -9
- package/dist/v2/core/types.d.ts +50 -12
- package/dist/v2/core/types.js +0 -3
- package/dist/v2/core/utils/checkout.d.ts +2 -2
- package/dist/v2/core/utils/checkout.js +7 -2
- package/dist/v2/core/utils/currency.d.ts +14 -0
- package/dist/v2/core/utils/currency.js +40 -0
- package/dist/v2/core/utils/index.d.ts +1 -0
- package/dist/v2/core/utils/index.js +2 -0
- package/dist/v2/core/utils/order.d.ts +11 -9
- package/dist/v2/core/utils/pluginConfig.d.ts +8 -0
- package/dist/v2/core/utils/pluginConfig.js +28 -0
- package/dist/v2/index.d.ts +3 -1
- package/dist/v2/index.js +1 -1
- package/dist/v2/react/components/FunnelScriptInjector.js +21 -0
- package/dist/v2/react/components/WhopCheckout.d.ts +24 -0
- package/dist/v2/react/components/WhopCheckout.js +231 -0
- package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +1 -1
- package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.js +181 -0
- package/dist/v2/react/hooks/payment-actions/useErrorAction.d.ts +9 -0
- package/dist/v2/react/hooks/payment-actions/useErrorAction.js +21 -0
- package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.js +187 -0
- package/dist/v2/react/hooks/payment-actions/useKessPayAction.d.ts +11 -0
- package/dist/v2/react/hooks/payment-actions/useKessPayAction.js +91 -0
- package/dist/v2/react/hooks/payment-actions/useMasterCardAction.d.ts +24 -0
- package/dist/v2/react/hooks/payment-actions/useMasterCardAction.js +221 -0
- package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.d.ts +15 -0
- package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.js +142 -0
- package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.d.ts +3 -0
- package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.js +13 -0
- package/dist/v2/react/hooks/payment-actions/useRedirectAction.d.ts +10 -0
- package/dist/v2/react/hooks/payment-actions/useRedirectAction.js +35 -0
- package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.js +192 -0
- package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.js +81 -0
- package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.d.ts +11 -0
- package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.js +84 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.d.ts +14 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.js +36 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.d.ts +31 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.js +212 -0
- package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.d.ts +14 -0
- package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.js +207 -0
- package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.d.ts +12 -0
- package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.js +101 -0
- package/dist/v2/react/hooks/useCheckoutQuery.d.ts +6 -0
- package/dist/v2/react/hooks/useCheckoutQuery.js +45 -0
- package/dist/v2/react/hooks/useGeoLocation.d.ts +2 -1
- package/dist/v2/react/hooks/useGeoLocation.js +4 -2
- package/dist/v2/react/hooks/useISOData.js +1 -1
- package/dist/v2/react/hooks/usePaymentPolling.d.ts +3 -3
- package/dist/v2/react/hooks/usePaymentQuery.d.ts +18 -5
- package/dist/v2/react/hooks/usePaymentQuery.js +63 -1015
- package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +3 -2
- package/dist/v2/react/hooks/usePaymentRetrieve.js +3 -1
- package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -48
- package/dist/v2/react/hooks/usePixelTracking.js +212 -514
- package/dist/v2/react/hooks/useShippingRatesQuery.js +13 -5
- package/dist/v2/react/hooks/useWhopPaymentPolling.d.ts +30 -0
- package/dist/v2/react/hooks/useWhopPaymentPolling.js +61 -0
- package/dist/v2/react/index.d.ts +7 -0
- package/dist/v2/react/index.js +4 -0
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +2 -1
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +3 -1
- package/dist/v2/react/providers/TagadaProvider.js +71 -2
- package/dist/v2/standalone/external-tracker.d.ts +52 -46
- package/dist/v2/standalone/external-tracker.js +205 -98
- package/dist/v2/standalone/index.d.ts +22 -0
- package/dist/v2/standalone/index.js +126 -1
- package/package.json +3 -3
- package/dist/react/utils/__tests__/urlUtils.test.d.ts +0 -1
- package/dist/react/utils/__tests__/urlUtils.test.js +0 -189
- package/dist/v2/core/__tests__/pathRemapping.test.d.ts +0 -11
- package/dist/v2/core/__tests__/pathRemapping.test.js +0 -776
|
@@ -4,18 +4,16 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* usePixelTracking Hook & Provider
|
|
5
5
|
*
|
|
6
6
|
* SDK-level pixel tracking based on runtime stepConfig.pixels injected
|
|
7
|
-
* by the CRM.
|
|
8
|
-
*
|
|
9
|
-
* integrations.
|
|
7
|
+
* by the CRM. Uses core/pixelMapping for event mapping and gating,
|
|
8
|
+
* keeping browser-specific init/fire logic here.
|
|
10
9
|
*/
|
|
11
10
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from 'react';
|
|
12
|
-
import {
|
|
11
|
+
import { resolvePixelEvents, } from '../../core/pixelMapping';
|
|
13
12
|
import { useStepConfig } from './useStepConfig';
|
|
14
13
|
const PixelTrackingContext = createContext(null);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Duplicate guard (time-window based)
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
19
17
|
function createDuplicateGuard(windowMs) {
|
|
20
18
|
const lastEvents = new Map();
|
|
21
19
|
return (eventName, parameters) => {
|
|
@@ -29,588 +27,288 @@ function createDuplicateGuard(windowMs) {
|
|
|
29
27
|
return true;
|
|
30
28
|
}
|
|
31
29
|
catch {
|
|
32
|
-
// If hashing fails for any reason, just allow the event
|
|
33
30
|
return true;
|
|
34
31
|
}
|
|
35
32
|
};
|
|
36
33
|
}
|
|
37
34
|
const shouldTrackEvent = createDuplicateGuard(5000);
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
*/
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Provider
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
42
38
|
export function PixelTrackingProvider({ children }) {
|
|
43
39
|
const { pixels } = useStepConfig();
|
|
44
40
|
const [pixelsInitialized, setPixelsInitialized] = useState(false);
|
|
45
41
|
const isMountedRef = useRef(true);
|
|
46
42
|
useEffect(() => {
|
|
47
43
|
isMountedRef.current = true;
|
|
48
|
-
return () => {
|
|
49
|
-
isMountedRef.current = false;
|
|
50
|
-
};
|
|
44
|
+
return () => { isMountedRef.current = false; };
|
|
51
45
|
}, []);
|
|
52
|
-
// Initialize
|
|
46
|
+
// ---- Initialize pixel scripts once ----
|
|
53
47
|
useEffect(() => {
|
|
54
48
|
if (!pixels || pixelsInitialized || !isMountedRef.current)
|
|
55
49
|
return;
|
|
56
50
|
try {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// TikTok - support multiple pixels
|
|
69
|
-
const tiktokPixels = pixels.tiktok;
|
|
70
|
-
if (tiktokPixels) {
|
|
71
|
-
if (Array.isArray(tiktokPixels)) {
|
|
72
|
-
tiktokPixels.forEach((pixel) => {
|
|
73
|
-
if (pixel.enabled && pixel.pixelId) {
|
|
74
|
-
initTikTokPixel(pixel.pixelId);
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Snapchat - support multiple pixels
|
|
80
|
-
const snapchatPixels = pixels.snapchat;
|
|
81
|
-
if (snapchatPixels) {
|
|
82
|
-
if (Array.isArray(snapchatPixels)) {
|
|
83
|
-
snapchatPixels.forEach((pixel) => {
|
|
84
|
-
if (pixel.enabled && pixel.pixelId) {
|
|
85
|
-
initSnapchatPixel(pixel.pixelId);
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// Pinterest - support multiple pixels
|
|
91
|
-
const pinterestPixels = pixels.pinterest;
|
|
92
|
-
if (pinterestPixels) {
|
|
93
|
-
if (Array.isArray(pinterestPixels)) {
|
|
94
|
-
pinterestPixels.forEach((pixel) => {
|
|
95
|
-
if (pixel.enabled && pixel.pixelId) {
|
|
96
|
-
initPinterestPixel(pixel.pixelId);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// GTM - support multiple containers
|
|
102
|
-
const gtmPixels = pixels.gtm;
|
|
103
|
-
if (gtmPixels) {
|
|
104
|
-
if (Array.isArray(gtmPixels)) {
|
|
105
|
-
gtmPixels.forEach((pixel) => {
|
|
106
|
-
if (pixel.enabled && pixel.containerId) {
|
|
107
|
-
initGTM(pixel.containerId);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
if (isMountedRef.current) {
|
|
51
|
+
pixels.facebook?.forEach((px) => { if (px.enabled && px.pixelId)
|
|
52
|
+
initMetaPixel(px.pixelId); });
|
|
53
|
+
pixels.tiktok?.forEach((px) => { if (px.enabled && px.pixelId)
|
|
54
|
+
initTikTokPixel(px.pixelId); });
|
|
55
|
+
pixels.snapchat?.forEach((px) => { if (px.enabled && px.pixelId)
|
|
56
|
+
initSnapchatPixel(px.pixelId); });
|
|
57
|
+
pixels.pinterest?.forEach((px) => { if (px.enabled && px.pixelId)
|
|
58
|
+
initPinterestPixel(px.pixelId); });
|
|
59
|
+
pixels.gtm?.forEach((px) => { if (px.enabled && px.containerId)
|
|
60
|
+
initGTM(px.containerId); });
|
|
61
|
+
if (isMountedRef.current)
|
|
113
62
|
setPixelsInitialized(true);
|
|
114
|
-
}
|
|
115
63
|
}
|
|
116
64
|
catch (error) {
|
|
117
|
-
|
|
118
|
-
if (typeof console !== 'undefined') {
|
|
119
|
-
console.error('[SDK Pixels] Error during pixel initialization:', error);
|
|
120
|
-
}
|
|
65
|
+
console.error('[SDK Pixels] Initialization error:', error);
|
|
121
66
|
}
|
|
122
67
|
}, [pixels, pixelsInitialized]);
|
|
68
|
+
// ---- Track function ----
|
|
123
69
|
const track = useCallback((eventName, parameters = {}) => {
|
|
124
|
-
if (!pixels || !pixelsInitialized || !isMountedRef.current)
|
|
70
|
+
if (!pixels || !pixelsInitialized || !isMountedRef.current)
|
|
125
71
|
return;
|
|
126
|
-
|
|
127
|
-
// Duplicate guard
|
|
128
|
-
if (!shouldTrackEvent(eventName, parameters)) {
|
|
72
|
+
if (!shouldTrackEvent(eventName, parameters))
|
|
129
73
|
return;
|
|
130
|
-
}
|
|
131
74
|
try {
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
const pixelArray = Array.isArray(facebookPixels)
|
|
136
|
-
? facebookPixels
|
|
137
|
-
: [facebookPixels];
|
|
138
|
-
const enabledPixels = pixelArray.filter((p) => p.enabled);
|
|
139
|
-
if (enabledPixels.length > 0) {
|
|
140
|
-
const { name, params } = mapMetaEvent(eventName, parameters);
|
|
141
|
-
// Track to all enabled Facebook pixels
|
|
142
|
-
enabledPixels.forEach(() => {
|
|
143
|
-
trackMetaEvent(name, params);
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
// TikTok - track to all enabled pixels
|
|
148
|
-
const tiktokPixels = pixels.tiktok;
|
|
149
|
-
if (tiktokPixels) {
|
|
150
|
-
const pixelArray = Array.isArray(tiktokPixels)
|
|
151
|
-
? tiktokPixels
|
|
152
|
-
: [tiktokPixels];
|
|
153
|
-
const enabledPixels = pixelArray.filter((p) => p.enabled);
|
|
154
|
-
if (enabledPixels.length > 0) {
|
|
155
|
-
const { name, params } = mapTikTokEvent(eventName, parameters);
|
|
156
|
-
// Track to all enabled TikTok pixels
|
|
157
|
-
enabledPixels.forEach(() => {
|
|
158
|
-
trackTikTokEvent(name, params);
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Snapchat - track to all enabled pixels
|
|
163
|
-
const snapchatPixels = pixels.snapchat;
|
|
164
|
-
if (snapchatPixels) {
|
|
165
|
-
const pixelArray = Array.isArray(snapchatPixels)
|
|
166
|
-
? snapchatPixels
|
|
167
|
-
: [snapchatPixels];
|
|
168
|
-
const enabledPixels = pixelArray.filter((p) => p.enabled);
|
|
169
|
-
if (enabledPixels.length > 0) {
|
|
170
|
-
const { name, params } = mapSnapchatEvent(eventName, parameters);
|
|
171
|
-
// Track to all enabled Snapchat pixels
|
|
172
|
-
enabledPixels.forEach(() => {
|
|
173
|
-
trackSnapchatEvent(name, params);
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
// Pinterest - track to all enabled pixels
|
|
178
|
-
const pinterestPixels = pixels.pinterest;
|
|
179
|
-
if (pinterestPixels) {
|
|
180
|
-
const pixelArray = Array.isArray(pinterestPixels)
|
|
181
|
-
? pinterestPixels
|
|
182
|
-
: [pinterestPixels];
|
|
183
|
-
const enabledPixels = pixelArray.filter((p) => p.enabled);
|
|
184
|
-
if (enabledPixels.length > 0) {
|
|
185
|
-
const { name, params } = mapPinterestEvent(eventName, parameters);
|
|
186
|
-
// Track to all enabled Pinterest pixels
|
|
187
|
-
enabledPixels.forEach(() => {
|
|
188
|
-
trackPinterestEvent(name, params);
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
// GTM - track to all enabled containers
|
|
193
|
-
const gtmPixels = pixels.gtm;
|
|
194
|
-
if (gtmPixels) {
|
|
195
|
-
const pixelArray = Array.isArray(gtmPixels)
|
|
196
|
-
? gtmPixels
|
|
197
|
-
: [gtmPixels];
|
|
198
|
-
const enabledPixels = pixelArray.filter((p) => p.enabled);
|
|
199
|
-
if (enabledPixels.length > 0) {
|
|
200
|
-
const { name, params } = mapGTMEvent(eventName, parameters);
|
|
201
|
-
// Track to all enabled GTM containers
|
|
202
|
-
enabledPixels.forEach(() => {
|
|
203
|
-
console.log('trackGTMEvent', name, params);
|
|
204
|
-
trackGTMEvent(name, params);
|
|
205
|
-
});
|
|
206
|
-
}
|
|
75
|
+
const events = resolvePixelEvents(pixels, eventName, parameters);
|
|
76
|
+
for (const { provider, mapped } of events) {
|
|
77
|
+
fire(provider, mapped.name, mapped.params);
|
|
207
78
|
}
|
|
208
79
|
}
|
|
209
80
|
catch (error) {
|
|
210
|
-
|
|
211
|
-
console.error('[SDK Pixels] Error tracking pixel event:', error);
|
|
212
|
-
}
|
|
81
|
+
console.error('[SDK Pixels] Tracking error:', error);
|
|
213
82
|
}
|
|
214
83
|
}, [pixels, pixelsInitialized]);
|
|
215
|
-
//
|
|
84
|
+
// ---- Auto page-view ----
|
|
216
85
|
useEffect(() => {
|
|
217
86
|
if (!pixelsInitialized || !isMountedRef.current)
|
|
218
87
|
return;
|
|
219
|
-
|
|
220
|
-
const pageViewTimeoutId = setTimeout(() => {
|
|
88
|
+
const id = setTimeout(() => {
|
|
221
89
|
if (isMountedRef.current) {
|
|
222
|
-
track('PageView', {
|
|
223
|
-
path: typeof window !== 'undefined' ? window.location.pathname : '',
|
|
224
|
-
});
|
|
90
|
+
track('PageView', { path: typeof window !== 'undefined' ? window.location.pathname : '' });
|
|
225
91
|
}
|
|
226
92
|
}, 0);
|
|
227
|
-
return () =>
|
|
228
|
-
if (pageViewTimeoutId) {
|
|
229
|
-
clearTimeout(pageViewTimeoutId);
|
|
230
|
-
}
|
|
231
|
-
};
|
|
93
|
+
return () => clearTimeout(id);
|
|
232
94
|
}, [pixelsInitialized, track]);
|
|
233
|
-
const value = useMemo(() => ({
|
|
234
|
-
track,
|
|
235
|
-
pixelsInitialized,
|
|
236
|
-
}), [track, pixelsInitialized]);
|
|
95
|
+
const value = useMemo(() => ({ track, pixelsInitialized }), [track, pixelsInitialized]);
|
|
237
96
|
return _jsx(PixelTrackingContext.Provider, { value: value, children: children });
|
|
238
97
|
}
|
|
239
|
-
/**
|
|
240
|
-
* Hook to access SDK pixel tracking.
|
|
241
|
-
* Must be used within TagadaProvider (which wraps PixelTrackingProvider).
|
|
242
|
-
*/
|
|
243
98
|
export function usePixelTracking() {
|
|
244
99
|
const context = useContext(PixelTrackingContext);
|
|
245
|
-
if (!context)
|
|
100
|
+
if (!context)
|
|
246
101
|
throw new Error('usePixelTracking must be used within a PixelTrackingProvider');
|
|
247
|
-
}
|
|
248
102
|
return context;
|
|
249
103
|
}
|
|
250
|
-
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// Browser-specific: fire an event to the correct global pixel function
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
108
|
+
function fire(provider, name, params) {
|
|
251
109
|
if (typeof window === 'undefined')
|
|
252
110
|
return;
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
|
|
111
|
+
const w = window;
|
|
112
|
+
switch (provider) {
|
|
113
|
+
case 'facebook':
|
|
114
|
+
w.fbq?.('track', name, params);
|
|
115
|
+
break;
|
|
116
|
+
case 'tiktok':
|
|
117
|
+
// TikTok handles page views via ttq.page(), not ttq.track('Pageview')
|
|
118
|
+
if (name === 'Pageview') {
|
|
119
|
+
w.ttq?.page?.();
|
|
262
120
|
}
|
|
263
121
|
else {
|
|
264
|
-
|
|
122
|
+
w.ttq?.track?.(name, params);
|
|
265
123
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
fbq('init', pixelId);
|
|
124
|
+
break;
|
|
125
|
+
case 'snapchat':
|
|
126
|
+
w.snaptr?.('track', name, params);
|
|
127
|
+
break;
|
|
128
|
+
case 'pinterest':
|
|
129
|
+
// Pinterest handles page views via pintrk('page'), not pintrk('track', 'pagevisit')
|
|
130
|
+
if (name === 'pagevisit') {
|
|
131
|
+
w.pintrk?.('page');
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
w.pintrk?.('track', name, params);
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
case 'gtm':
|
|
138
|
+
fireGTM(name, params);
|
|
139
|
+
break;
|
|
283
140
|
}
|
|
284
141
|
}
|
|
285
|
-
function
|
|
286
|
-
|
|
142
|
+
function fireGTM(event, params) {
|
|
143
|
+
try {
|
|
144
|
+
const w = window;
|
|
145
|
+
if (w.gtag) {
|
|
146
|
+
w.gtag('event', event, params);
|
|
147
|
+
}
|
|
148
|
+
else if (w.dataLayer) {
|
|
149
|
+
w.dataLayer.push({ event, ...params });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error('[SDK GTM] Error:', error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
157
|
+
// ===========================================================================
|
|
158
|
+
// Pixel initialization (browser-only)
|
|
159
|
+
// All pixel globals are accessed via `win` typed as `any` to avoid
|
|
160
|
+
// `declare global` augmentation issues across tsconfig scopes.
|
|
161
|
+
// ===========================================================================
|
|
162
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
163
|
+
const win = (typeof window !== 'undefined' ? window : undefined);
|
|
164
|
+
function initMetaPixel(pixelId) {
|
|
165
|
+
if (!win || win.fbq)
|
|
287
166
|
return;
|
|
288
|
-
const
|
|
289
|
-
|
|
167
|
+
const n = function (...args) {
|
|
168
|
+
if (n.callMethod)
|
|
169
|
+
n.callMethod(...args);
|
|
170
|
+
else
|
|
171
|
+
n.queue.push(args);
|
|
172
|
+
};
|
|
173
|
+
n.queue = [];
|
|
174
|
+
n.loaded = true;
|
|
175
|
+
n.version = '2.0';
|
|
176
|
+
win.fbq = n;
|
|
177
|
+
if (!win._fbq)
|
|
178
|
+
win._fbq = n;
|
|
179
|
+
const t = document.createElement('script');
|
|
180
|
+
t.async = true;
|
|
181
|
+
t.src = 'https://connect.facebook.net/en_US/fbevents.js';
|
|
182
|
+
const s = document.getElementsByTagName('script')[0];
|
|
183
|
+
s?.parentNode?.insertBefore(t, s);
|
|
184
|
+
win.fbq('init', pixelId);
|
|
290
185
|
}
|
|
291
186
|
function initTikTokPixel(pixelId) {
|
|
292
|
-
if (
|
|
187
|
+
if (!win)
|
|
293
188
|
return;
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const ttq =
|
|
298
|
-
function (...args) {
|
|
299
|
-
ttq.queue.push(args);
|
|
300
|
-
};
|
|
301
|
-
if (!ttq.queue) {
|
|
302
|
-
ttq.queue = [];
|
|
303
|
-
}
|
|
304
|
-
w.ttq = ttq;
|
|
189
|
+
// Initialize TikTok base code once (mirrors official TikTok snippet)
|
|
190
|
+
if (!win.ttq) {
|
|
191
|
+
win.TiktokAnalyticsObject = 'ttq';
|
|
192
|
+
const ttq = (win.ttq = win.ttq || []);
|
|
305
193
|
ttq.methods = [
|
|
306
|
-
'page',
|
|
307
|
-
'
|
|
308
|
-
'
|
|
309
|
-
'instances',
|
|
310
|
-
'debug',
|
|
311
|
-
'on',
|
|
312
|
-
'off',
|
|
313
|
-
'once',
|
|
314
|
-
'ready',
|
|
315
|
-
'alias',
|
|
316
|
-
'group',
|
|
317
|
-
'enableCookie',
|
|
318
|
-
'disableCookie',
|
|
194
|
+
'page', 'track', 'identify', 'instances', 'debug', 'on', 'off',
|
|
195
|
+
'once', 'ready', 'alias', 'group', 'enableCookie', 'disableCookie',
|
|
196
|
+
'holdConsent', 'revokeConsent', 'grantConsent',
|
|
319
197
|
];
|
|
320
|
-
ttq.setAndDefer = function (
|
|
321
|
-
|
|
322
|
-
target.queue.push([method, ...args]);
|
|
323
|
-
};
|
|
198
|
+
ttq.setAndDefer = function (t, e) {
|
|
199
|
+
t[e] = function (...args) { t.push([e, ...args]); };
|
|
324
200
|
};
|
|
325
201
|
for (const method of ttq.methods) {
|
|
326
202
|
ttq.setAndDefer(ttq, method);
|
|
327
203
|
}
|
|
328
|
-
ttq.
|
|
329
|
-
const
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const s = d.getElementsByTagName(t)[0];
|
|
335
|
-
s.parentNode.insertBefore(a, s);
|
|
204
|
+
ttq.instance = function (t) {
|
|
205
|
+
const e = ttq._i[t] || [];
|
|
206
|
+
for (const method of ttq.methods) {
|
|
207
|
+
ttq.setAndDefer(e, method);
|
|
208
|
+
}
|
|
209
|
+
return e;
|
|
336
210
|
};
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
211
|
+
ttq.load = function (e, n) {
|
|
212
|
+
const r = 'https://analytics.tiktok.com/i18n/pixel/events.js';
|
|
213
|
+
ttq._i = ttq._i || {};
|
|
214
|
+
ttq._i[e] = [];
|
|
215
|
+
ttq._i[e]._u = r;
|
|
216
|
+
ttq._t = ttq._t || {};
|
|
217
|
+
ttq._t[e] = +new Date();
|
|
218
|
+
ttq._o = ttq._o || {};
|
|
219
|
+
ttq._o[e] = n || {};
|
|
220
|
+
const s = document.createElement('script');
|
|
221
|
+
s.type = 'text/javascript';
|
|
222
|
+
s.async = true;
|
|
223
|
+
s.src = r + '?sdkid=' + e + '&lib=ttq';
|
|
224
|
+
const p = document.getElementsByTagName('script')[0];
|
|
225
|
+
p?.parentNode?.insertBefore(s, p);
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
// Skip if this specific pixel ID is already loaded
|
|
229
|
+
if (win.ttq?._i?.[pixelId])
|
|
346
230
|
return;
|
|
347
|
-
|
|
348
|
-
ttq
|
|
231
|
+
win.ttq.load(pixelId);
|
|
232
|
+
// Note: ttq.page() is NOT called here — the Provider's auto page-view
|
|
233
|
+
// effect fires track('PageView') which handles it. Calling both would
|
|
234
|
+
// double-count page views in TikTok Ads Manager.
|
|
349
235
|
}
|
|
350
236
|
function initSnapchatPixel(pixelId) {
|
|
351
|
-
if (
|
|
237
|
+
if (!win || win.snaptr)
|
|
352
238
|
return;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
return;
|
|
358
|
-
const a = (function (...args) {
|
|
359
|
-
if (a.handleRequest) {
|
|
360
|
-
a.handleRequest(...args);
|
|
361
|
-
}
|
|
362
|
-
else {
|
|
363
|
-
a.queue.push(args);
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
a.queue = [];
|
|
367
|
-
w.snaptr = a;
|
|
368
|
-
const s = 'script';
|
|
369
|
-
const r = d.createElement(s);
|
|
370
|
-
r.async = true;
|
|
371
|
-
r.src = 'https://sc-static.net/scevent.min.js';
|
|
372
|
-
const u = d.getElementsByTagName(tagName)[0];
|
|
373
|
-
u.parentNode?.insertBefore(r, u);
|
|
374
|
-
})(window, document, 'script');
|
|
375
|
-
const snaptr = window.snaptr;
|
|
376
|
-
snaptr?.('init', pixelId);
|
|
377
|
-
}
|
|
378
|
-
function trackSnapchatEvent(name, params) {
|
|
379
|
-
if (typeof window === 'undefined' || !window.snaptr)
|
|
380
|
-
return;
|
|
381
|
-
const snaptr = window.snaptr;
|
|
382
|
-
snaptr?.('track', name, params);
|
|
383
|
-
}
|
|
384
|
-
function initPinterestPixel(pixelId) {
|
|
385
|
-
if (typeof window === 'undefined')
|
|
386
|
-
return;
|
|
387
|
-
if (window.pintrk)
|
|
388
|
-
return;
|
|
389
|
-
(function (w, d, tagName) {
|
|
390
|
-
if (w.pintrk)
|
|
391
|
-
return;
|
|
392
|
-
const a = (function (...args) {
|
|
239
|
+
const a = function (...args) {
|
|
240
|
+
if (a.handleRequest)
|
|
241
|
+
a.handleRequest(...args);
|
|
242
|
+
else
|
|
393
243
|
a.queue.push(args);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
const pintrk = window.pintrk;
|
|
404
|
-
pintrk?.('load', pixelId);
|
|
405
|
-
pintrk?.('page');
|
|
244
|
+
};
|
|
245
|
+
a.queue = [];
|
|
246
|
+
win.snaptr = a;
|
|
247
|
+
const r = document.createElement('script');
|
|
248
|
+
r.async = true;
|
|
249
|
+
r.src = 'https://sc-static.net/scevent.min.js';
|
|
250
|
+
const u = document.getElementsByTagName('script')[0];
|
|
251
|
+
u?.parentNode?.insertBefore(r, u);
|
|
252
|
+
win.snaptr('init', pixelId);
|
|
406
253
|
}
|
|
407
|
-
function
|
|
408
|
-
if (
|
|
254
|
+
function initPinterestPixel(pixelId) {
|
|
255
|
+
if (!win || win.pintrk)
|
|
409
256
|
return;
|
|
410
|
-
const
|
|
411
|
-
|
|
257
|
+
const a = function (...args) { a.queue.push(args); };
|
|
258
|
+
a.queue = [];
|
|
259
|
+
win.pintrk = a;
|
|
260
|
+
const s = document.createElement('script');
|
|
261
|
+
s.async = true;
|
|
262
|
+
s.src = 'https://s.pinimg.com/ct/core.js';
|
|
263
|
+
const u = document.getElementsByTagName('script')[0];
|
|
264
|
+
u?.parentNode?.insertBefore(s, u);
|
|
265
|
+
win.pintrk('load', pixelId);
|
|
266
|
+
// Note: pintrk('page') is NOT called here — the Provider's auto page-view
|
|
267
|
+
// effect handles it via fire(). Calling both would double-count page views.
|
|
412
268
|
}
|
|
413
269
|
function initGTM(containerId) {
|
|
414
|
-
if (
|
|
270
|
+
if (!win || !containerId)
|
|
415
271
|
return;
|
|
416
|
-
|
|
272
|
+
const isGtmContainer = containerId.startsWith('GTM-');
|
|
273
|
+
const scriptUrlPart = isGtmContainer
|
|
274
|
+
? `googletagmanager.com/gtm.js?id=${containerId}`
|
|
275
|
+
: `googletagmanager.com/gtag/js?id=${containerId}`;
|
|
276
|
+
if (document.querySelector(`script[src*="${scriptUrlPart}"]`))
|
|
417
277
|
return;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
// Initialize dataLayer before GTM script (Google's official pattern)
|
|
424
|
-
window.dataLayer = window.dataLayer || [];
|
|
425
|
-
// Push gtm.start event (must be done before script loads)
|
|
426
|
-
window.dataLayer.push({
|
|
427
|
-
'gtm.start': new Date().getTime(),
|
|
428
|
-
event: 'gtm.js',
|
|
429
|
-
});
|
|
430
|
-
// Create and inject GTM script (Google's official pattern)
|
|
431
|
-
// This matches Google's exact implementation from their documentation
|
|
432
|
-
(function (w, d, s, l, i) {
|
|
433
|
-
const f = d.getElementsByTagName(s)[0];
|
|
434
|
-
const j = d.createElement(s);
|
|
435
|
-
const dl = l != 'dataLayer' ? '&l=' + l : '';
|
|
278
|
+
win.dataLayer = win.dataLayer || [];
|
|
279
|
+
if (isGtmContainer) {
|
|
280
|
+
win.dataLayer.push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });
|
|
281
|
+
const f = document.getElementsByTagName('script')[0];
|
|
282
|
+
const j = document.createElement('script');
|
|
436
283
|
j.async = true;
|
|
437
|
-
j.src = 'https://www.googletagmanager.com/gtm.js?id=' +
|
|
438
|
-
|
|
439
|
-
if (f && f.parentNode) {
|
|
284
|
+
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + containerId;
|
|
285
|
+
if (f?.parentNode)
|
|
440
286
|
f.parentNode.insertBefore(j, f);
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const noscript = document.createElement('noscript');
|
|
453
|
-
const iframe = document.createElement('iframe');
|
|
454
|
-
iframe.src = `https://www.googletagmanager.com/ns.html?id=${containerId}`;
|
|
455
|
-
iframe.height = '0';
|
|
456
|
-
iframe.width = '0';
|
|
457
|
-
iframe.style.display = 'none';
|
|
458
|
-
iframe.style.visibility = 'hidden';
|
|
459
|
-
noscript.appendChild(iframe);
|
|
460
|
-
// Insert noscript at the beginning of body
|
|
461
|
-
const body = document.body || document.getElementsByTagName('body')[0];
|
|
462
|
-
if (body) {
|
|
463
|
-
body.insertBefore(noscript, body.firstChild);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
function trackGTMEvent(event, params = {}) {
|
|
467
|
-
if (typeof window === 'undefined') {
|
|
468
|
-
console.warn('[SDK GTM] Window not available, event not tracked:', event);
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
// Ensure dataLayer exists (should be initialized by initGTM, but double-check)
|
|
472
|
-
if (!window.dataLayer) {
|
|
473
|
-
console.warn('[SDK GTM] dataLayer not initialized, initializing now...');
|
|
474
|
-
window.dataLayer = [];
|
|
475
|
-
}
|
|
476
|
-
try {
|
|
477
|
-
const eventData = {
|
|
478
|
-
event,
|
|
479
|
-
...params,
|
|
480
|
-
};
|
|
481
|
-
console.log('[SDK GTM] Pushing event to dataLayer:', eventData);
|
|
482
|
-
window.dataLayer.push(eventData);
|
|
483
|
-
console.log('[SDK GTM] Event pushed successfully. Current dataLayer length:', window.dataLayer.length);
|
|
484
|
-
}
|
|
485
|
-
catch (error) {
|
|
486
|
-
if (typeof console !== 'undefined') {
|
|
487
|
-
console.error('[SDK GTM] Error tracking event:', error);
|
|
488
|
-
}
|
|
287
|
+
else
|
|
288
|
+
(document.head || document.getElementsByTagName('head')[0])?.appendChild(j);
|
|
289
|
+
const noscript = document.createElement('noscript');
|
|
290
|
+
const iframe = document.createElement('iframe');
|
|
291
|
+
iframe.src = `https://www.googletagmanager.com/ns.html?id=${containerId}`;
|
|
292
|
+
iframe.height = '0';
|
|
293
|
+
iframe.width = '0';
|
|
294
|
+
iframe.style.display = 'none';
|
|
295
|
+
iframe.style.visibility = 'hidden';
|
|
296
|
+
noscript.appendChild(iframe);
|
|
297
|
+
(document.body || document.getElementsByTagName('body')[0])?.insertBefore(noscript, document.body?.firstChild ?? null);
|
|
489
298
|
}
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
function
|
|
493
|
-
return { name: eventName, params: parameters };
|
|
494
|
-
}
|
|
495
|
-
function mapTikTokEvent(eventName, parameters) {
|
|
496
|
-
// TikTok naming is usually aligned; adjust here if needed later
|
|
497
|
-
return { name: eventName, params: parameters };
|
|
498
|
-
}
|
|
499
|
-
function mapSnapchatEvent(eventName, parameters) {
|
|
500
|
-
return { name: eventName, params: parameters };
|
|
501
|
-
}
|
|
502
|
-
function mapPinterestEvent(eventName, parameters) {
|
|
503
|
-
// Pinterest uses lowercase event names
|
|
504
|
-
const pinterestEventMap = {
|
|
505
|
-
PageView: 'pagevisit',
|
|
506
|
-
ViewContent: 'viewcontent',
|
|
507
|
-
AddToCart: 'addtocart',
|
|
508
|
-
InitiateCheckout: 'initiatecheckout',
|
|
509
|
-
AddPaymentInfo: 'addpaymentinfo',
|
|
510
|
-
Purchase: 'checkout',
|
|
511
|
-
Lead: 'lead',
|
|
512
|
-
CompleteRegistration: 'signup',
|
|
513
|
-
};
|
|
514
|
-
const pinterestEventName = pinterestEventMap[eventName] ?? eventName.toLowerCase();
|
|
515
|
-
// Transform parameters for Pinterest
|
|
516
|
-
const pinterestParams = transformPinterestParameters(eventName, parameters);
|
|
517
|
-
return { name: pinterestEventName, params: pinterestParams };
|
|
518
|
-
}
|
|
519
|
-
function transformPinterestParameters(eventName, parameters) {
|
|
520
|
-
const pinParams = { ...parameters };
|
|
521
|
-
// Pinterest uses 'value' and 'order_quantity' as primary event data
|
|
522
|
-
// Ensure currency is uppercase
|
|
523
|
-
if (pinParams.currency) {
|
|
524
|
-
pinParams.currency = String(pinParams.currency).toUpperCase();
|
|
525
|
-
}
|
|
526
|
-
// Convert to major units if currency is present
|
|
527
|
-
if (pinParams.currency && pinParams.value) {
|
|
528
|
-
try {
|
|
529
|
-
pinParams.value = minorUnitsToMajorUnits(Number(pinParams.value), String(pinParams.currency));
|
|
530
|
-
}
|
|
531
|
-
catch {
|
|
532
|
-
// Fallback to simple division by 100
|
|
533
|
-
pinParams.value = Number(pinParams.value) / 100;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
// Ensure numeric values
|
|
537
|
-
if (pinParams.value !== undefined) {
|
|
538
|
-
pinParams.value = Number(pinParams.value);
|
|
539
|
-
}
|
|
540
|
-
if (pinParams.order_quantity !== undefined) {
|
|
541
|
-
pinParams.order_quantity = Number(pinParams.order_quantity);
|
|
542
|
-
}
|
|
543
|
-
// Transform contents to Pinterest format (product_id array)
|
|
544
|
-
if (pinParams.contents && Array.isArray(pinParams.contents)) {
|
|
545
|
-
pinParams.line_items = pinParams.contents.map((item) => ({
|
|
546
|
-
product_id: item.content_id,
|
|
547
|
-
product_name: item.content_name,
|
|
548
|
-
product_category: item.content_category,
|
|
549
|
-
product_price: item.price ? Number(item.price) : undefined,
|
|
550
|
-
product_quantity: item.quantity ? Number(item.quantity) : undefined,
|
|
551
|
-
}));
|
|
552
|
-
}
|
|
553
|
-
return pinParams;
|
|
554
|
-
}
|
|
555
|
-
function mapGTMEvent(eventName, parameters) {
|
|
556
|
-
// Map standard event names to GTM event names
|
|
557
|
-
const gtmEventMap = {
|
|
558
|
-
PageView: 'page_view',
|
|
559
|
-
AddPaymentInfo: 'add_payment_info',
|
|
560
|
-
AddToCart: 'add_to_cart',
|
|
561
|
-
InitiateCheckout: 'begin_checkout',
|
|
562
|
-
Purchase: 'purchase',
|
|
563
|
-
ViewContent: 'view_item',
|
|
564
|
-
CompleteRegistration: 'sign_up',
|
|
565
|
-
};
|
|
566
|
-
const gtmEventName = gtmEventMap[eventName] ?? eventName.toLowerCase();
|
|
567
|
-
// Transform parameters for GTM
|
|
568
|
-
const gtmParams = transformGTMParameters(eventName, parameters);
|
|
569
|
-
return { name: gtmEventName, params: gtmParams };
|
|
570
|
-
}
|
|
571
|
-
function transformGTMParameters(eventName, parameters) {
|
|
572
|
-
const gtmParameters = { ...parameters };
|
|
573
|
-
// Ensure currency is uppercase
|
|
574
|
-
if (gtmParameters.currency) {
|
|
575
|
-
gtmParameters.currency = String(gtmParameters.currency).toUpperCase();
|
|
576
|
-
}
|
|
577
|
-
// Transform currency values to major units if needed
|
|
578
|
-
if (gtmParameters.currency && gtmParameters.value) {
|
|
579
|
-
try {
|
|
580
|
-
gtmParameters.value = minorUnitsToMajorUnits(Number(gtmParameters.value), String(gtmParameters.currency));
|
|
299
|
+
else {
|
|
300
|
+
if (!win.gtag) {
|
|
301
|
+
win.gtag = function (..._args) { win.dataLayer.push(arguments); };
|
|
581
302
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
gtmParameters.value = Number(gtmParameters.value);
|
|
593
|
-
}
|
|
594
|
-
if (gtmParameters.num_items !== undefined) {
|
|
595
|
-
gtmParameters.num_items = Number(gtmParameters.num_items);
|
|
596
|
-
}
|
|
597
|
-
// Transform contents to a format better suited for GTM
|
|
598
|
-
if (gtmParameters.contents && Array.isArray(gtmParameters.contents)) {
|
|
599
|
-
gtmParameters.items = gtmParameters.contents.map((item) => ({
|
|
600
|
-
item_id: item.content_id,
|
|
601
|
-
item_name: item.content_name,
|
|
602
|
-
item_category: item.content_category,
|
|
603
|
-
price: item.price ? Number(item.price) : undefined,
|
|
604
|
-
quantity: item.quantity ? Number(item.quantity) : undefined,
|
|
605
|
-
}));
|
|
606
|
-
// Keep original contents for compatibility
|
|
607
|
-
gtmParameters.contents = gtmParameters.contents.map((item) => ({
|
|
608
|
-
id: item.content_id,
|
|
609
|
-
name: item.content_name,
|
|
610
|
-
category: item.content_category,
|
|
611
|
-
price: item.price ? Number(item.price) : undefined,
|
|
612
|
-
quantity: item.quantity ? Number(item.quantity) : undefined,
|
|
613
|
-
}));
|
|
303
|
+
win.gtag('js', new Date());
|
|
304
|
+
win.gtag('config', containerId);
|
|
305
|
+
const script = document.createElement('script');
|
|
306
|
+
script.async = true;
|
|
307
|
+
script.src = 'https://www.googletagmanager.com/gtag/js?id=' + containerId;
|
|
308
|
+
const firstScript = document.getElementsByTagName('script')[0];
|
|
309
|
+
if (firstScript?.parentNode)
|
|
310
|
+
firstScript.parentNode.insertBefore(script, firstScript);
|
|
311
|
+
else
|
|
312
|
+
(document.head || document.getElementsByTagName('head')[0])?.appendChild(script);
|
|
614
313
|
}
|
|
615
|
-
return gtmParameters;
|
|
616
314
|
}
|