PageSourceSearch

https://www.simplywise.com/static-pages/static/js/tracking/trackingService.js

js simplywise.com collected 2026-09-28 08:41:13 UTC 7,226 bytes, 197 lines download raw bytes

1/**
2 * Client-side Tracking Service
3 * Makes API calls to tracking service
4 * Migrated from src/services/tracking/index.ts
5 */
6
7const TrackingService = {
8    /**
9     * Record tracking data
10     * @param {Object} data - Tracking data to record
11     * @returns {Promise<{success: boolean, message: string, ip: string}>}
12     */
13    recordData: async function (data) {
14        try {
15            const response = await fetch(
16                'https://tracking.simplywise.com/record',
17                {
18                    method: 'POST',
19                    headers: {
20                        'Content-Type': 'application/json',
21                    },
22                    body: JSON.stringify(data),
23                    // A download click navigates to the store right after
24                    // this; keepalive lets the request finish anyway.
25                    keepalive: true,
26                }
27            );
28
29            const result = await response.json();
30            Logger.log('[TrackingService] Data recorded:', result.success);
31            return result;
32        } catch (error) {
33            Logger.error('[TrackingService] Error recording data:', error);
34            return {
35                success: false,
36                message: error.message,
37                ip: data.ip_address || '',
38            };
39        }
40    },
41
42    /**
43     * Check tracking data
44     * @param {Object} data - Data to check
45     * @returns {Promise<{success: boolean, message: string, ip: string}>}
46     */
47    checkData: async function (data) {
48        try {
49            const response = await fetch(
50                'https://tracking.simplywise.com/check',
51                {
52                    method: 'POST',
53                    headers: {
54                        'Content-Type': 'application/json',
55                    },
56                    body: JSON.stringify(data),
57                }
58            );
59
60            const result = await response.json();
61            return result;
62        } catch (error) {
63            Logger.error('[TrackingService] Error checking data:', error);
64            return {
65                success: false,
66                message: error.message,
67                ip: data.ip_address || '',
68            };
69        }
70    },
71
72    /**
73     * Get IP address. Looked up once per page: the same address is what
74     * the download record is keyed on, so callers may warm it early.
75     * @returns {Promise<string>}
76     */
77    getIpAddress: function () {
78        if (!this._ipAddress) {
79            this._ipAddress = fetch('https://api.ipify.org?format=json')
80                .then(function (response) {
81                    return response.json();
82                })
83                .then(function (data) {
84                    return data.ip;
85                })
86                .catch(
87                    function (error) {
88                        Logger.error(
89                            '[TrackingService] Error getting IP address:',
90                            error
91                        );
92                        // Let the next caller try again.
93                        this._ipAddress = null;
94                        return '';
95                    }.bind(this)
96                );
97        }
98        return this._ipAddress;
99    },
100
101    /**
102     * Send a Facebook conversion event server-side (Conversions API).
103     * Used on pages where the Facebook Pixel is not loaded - the backend
104     * forwards the event to Facebook on our behalf.
105     * @param {string} eventName - Facebook event name (e.g. 'AddToCart')
106     * @param {Object} options
107     * @param {string|null} [options.gaId]
108     * @param {string|null} [options.facebookClickId] - fbclid from the URL
109     * @param {string|null} [options.facebookBrowserId]
110     * @param {string|null} [options.ipAddress]
111     * @param {string|null} [options.userAgent]
112     * @param {Object|null} [options.eventData]
113     * @param {string} [options.phoneNumber]
114     * @returns {Promise<Object>}
115     */
116    sendFbEvent: async function (eventName, options) {
117        const opts = options || {};
118        try {
119            const response = await fetch(
120                'https://api.simplywise.com/api/v2/tracking/send-fb-event',
121                {
122                    method: 'POST',
123                    headers: {
124                        'Content-Type': 'application/json',
125                    },
126                    body: JSON.stringify({
127                        event_name: eventName,
128                        gaid: opts.gaId || null,
129                        facebook_click_id: opts.facebookClickId || null,
130                        facebook_browser_id: opts.facebookBrowserId || null,
131                        ip_address: opts.ipAddress || null,
132                        user_agent: opts.userAgent || null,
133                        event_data: opts.eventData || null,
134                        phone_number: opts.phoneNumber || null,
135                    }),
136                }
137            );
138
139            const result = await response.json();
140            Logger.log('[TrackingService] FB event sent:', eventName);
141            return result;
142        } catch (error) {
143            Logger.error('[TrackingService] Error sending FB event:', error);
144            return { success: false, message: error.message };
145        }
146    },
147
148    /**
149     * Send an Amplitude event server-side via the backend endpoint.
150     * Used on ad landing pages when the visitor has not granted statistics
151     * consent, so the client-side Amplitude SDK is blocked by Cookiebot.
152     * The backend forwards the event to Amplitude's HTTP API.
153     * @param {string} eventName - Amplitude event name (maps to event_type)
154     * @param {Object} options
155     * @param {Object} [options.eventProperties]
156     * @param {string} options.deviceId - Consent-aware visitor id
157     * @param {string|null}
157 [options.userAgent]
158     * @returns {Promise<Object>}
159     */
160    sendAmplitudeEvent: async function (eventName, options) {
161        const opts = options || {};
162        try {
163            const response = await fetch(
164                'https://api.simplywise.com/api/v2/tracking/amplitude-event',
165                {
166                    method: 'POST',
167                    headers: {
168                        'Content-Type': 'application/json',
169                    },
170                    body: JSON.stringify({
171                        event_type: eventName,
172                        event_properties: opts.eventProperties || {},
173                        device_id: opts.deviceId || null,
174                        user_agent: opts.userAgent || null,
175                        platform: 'web',
176                        time: Date.now(),
177                    }),
178                }
179            );
180
181            const result = await response.json();
182            Logger.log('[TrackingService] Amplitude event sent:', eventName);
183            return result;
184        } catch (error) {
185            Logger.error(
186                '[TrackingService] Error sending Amplitude event:',
187                error
188            );
189            return { success: false, message: error.message };
190        }
191    },
192};
193
194// Export for use in browser
195if (typeof window !== 'undefined') {
196    window.TrackingService = TrackingService;
197}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.