PageSourceSearch

https://pb-law.com/wp-content/plugins/sticky-device-registration/device-registration-client.js

js pb-law.com collected 2026-10-06 18:11:08 UTC 8,236 bytes, 255 lines download raw bytes

1/**
2 * Device Registration Client Script for Sticky Note Tool Devices
3 * 
4 * This script can be embedded on client websites to automatically register
5 * user devices with the central device management system.
6 * 
7 * Usage:
8 * 1. Replace API_ENDPOINT with your WordPress site URL + /wp-json/sntd/v1/register-device
9 * 2. Replace YOUR_API_KEY with your actual API key
10 * 3. Include this script on pages where you want to track devices
11 * 4. Call registerDevice(userEmail, projectId) when user logs in or visits
12 */
13
14class DeviceRegistration {
15    constructor(config) {
16        this.apiEndpoint = config.apiEndpoint;
17        this.apiKey = config.apiKey;
18        this.debug = config.debug || false;
19    }
20
21    /**
22     * Detect device information
23     */
24    detectDevice() {
25        const deviceInfo = {
26            user_agent: navigator.userAgent,
27            screen_width: screen.width,
28            screen_height: screen.height,
29            platform: navigator.platform,
30            browser: this.detectBrowser(),
31            device_type: this.detectDeviceType(),
32            language: navigator.language,
33            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
34            viewport_width: window.innerWidth,
35            viewport_height: window.innerHeight
36        };
37
38        if (this.debug) {
39            console.log('Device info detected:', deviceInfo);
40        }
41
42        return deviceInfo;
43    }
44
45    /**
46     * Detect browser name
47     */
48    detectBrowser() {
49        const userAgent = navigator.userAgent;
50
51        if (userAgent.includes('Chrome') && !userAgent.includes('Edg')) {
52            return 'Chrome';
53        } else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
54            return 'Safari';
55        } else if (userAgent.includes('Firefox')) {
56            return 'Firefox';
57        } else if (userAgent.includes('Edg')) {
58            return 'Edge';
59        } else if (userAgent.includes('Opera') || userAgent.includes('OPR')) {
60            return 'Opera';
61        } else {
62            return 'Unknown';
63        }
64    }
65
66    /**
67     * Detect device type
68     */
69    detectDeviceType() {
70        const userAgent = navigator.userAgent;
71
72        if (/tablet|ipad|playbook|silk/i.test(userAgent)) {
73            return 'tablet';
74        } else if (/mobile|iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(userAgent)) {
75            return 'mobile';
76        } else {
77            return 'desktop';
78        }
79    }
80
81    /**
82     * Register device with the API
83     */
84    async registerDevice(userEmail, projectId = null, websiteUrl = null) {
85        try {
86            const deviceInfo = this.detectDevice();
87
88            const requestData = {
89                api_key: this.apiKey,
90                device_info: deviceInfo,
91                website_url: websiteUrl || window.location.origin
92            };
93
94            if (userEmail) {
95                requestData.user_email = userEmail;
96            }
97
98            if (projectId) {
99                requestData.project_id = projectId;
100            }
101
102            const response = await fetch(this.apiEndpoint, {
103                method: 'POST',
104                // keepalive lets this POST finish even though the consent
105                // handler navigates immediately after firing it (no await),
106                // so the portal device record is still created without the
107                // user waiting on the round-trip.
108                keepalive: true,
109                headers: {
110                    'Content-Type': 'application/json',
111                    'X-API-Key': this.apiKey
112                },
113                body: JSON.stringify(requestData)
114            });
115
116            const data = await response.json();
117
118            if (this.debug) {
119                console.log('Device registration response:', data);
120            }
121
122            if (data.success) {
123                // Store device ID in localStorage for future updates
124                localStorage.setItem('sntd_device_id', data.device_id);
125                localStorage.setItem('sntd_last_registration', Date.now());
126
127                return {
128                    success: true,
129                    deviceId: data.device_id,
130                    action: data.action,
131                    message: data.message
132                };
133            } else {
134                throw new Error(data.message || 'Registration failed');
135            }
136
137        } catch (error) {
138            console.error('Device registration failed:', error);
139
140            return {
141                success: false,
142                error: error.message
143            };
144        }
145    }
146
147    /**
148     * Update device activity (heartbeat)
149     */
150    async updateDevice(userEmail) {
151        try {
152            const deviceInfo = this.detectDevice();
153
154            const requestData = {
155                user_email: userEmail,
156                api_key: this.apiKey,
157                device_info: deviceInfo
158            };
159
160            const response = await fetch(this.apiEndpoint.replace('/register-device', '/update-device'), {
161                method: 'PUT',
162                headers: {
163                    'Content-Type': 'application/json',
164                    'X-API-Key': this.apiKey
165                },
166                body: JSON.stringify(requestData)
167            });
168
169            const data = await response.json();
170
171            if (this.debug) {
172                console.log('Device update response:', data);
173            }
174
175            return data;
176
177        } catch (error) {
178            console.error('Device update failed:', error);
179            return { success: false, error: error.message };
180        }
181    }
182
183    /**
184     * Auto-register device when user is detected
185     * This can be called on page load or when user logs in
186     */
187    autoRegister(userEmail, projectId = null) {
188        // Check if we've registered recently (within last hour)
189        const lastRegistration = localStorage.getItem('sntd_last_registration');
190        const oneHour = 60 * 60 * 1000; // 1 hour in milliseconds
191
192        if (lastRegistration && (Date.now() - parseInt(lastRegistration)) < oneHour) {
193            if (this.debug) {
194                console.log('Device already registered recently, skipping...');
195            }
196            return;
197        }
198
199        return this.registerDevice(userEmail, projectId);
200    }
201
202    /**
203     * Start heartbeat to keep device active
204     */
205    startHeartbeat(userEmail, intervalMinutes = 15) {
206        const intervalMs = intervalMinutes * 60 * 1000;
207
208        const heartbeat = () => {
209            this.updateDevice(userEmail);
210        };
211
212        // Initial heartbeat
213        setTimeout(heartbeat, 5000); // Wait 5 seconds after page load
214
215        // Regular heartbeat
216        setInterval(heartbeat, intervalMs);
217
218        if (this.debug) {
219            console.log(`Device heartbeat started (${intervalMinutes} minutes interval)`);
220        }
221    }
222}
223
224// Example usage:
225/*
226const deviceRegistration = new DeviceRegistration({
227    apiEndpoint: 'https://your-wordpress-site.com/wp-json/sntd/v1/register-device',
228    apiKey: 'your-api-key-here',
229    debug: true // Set to false in production
230});
231
232// Register device when user logs in or visits
233deviceRegistration.registerDevice('[email protected]', 123)
234    .then(result => {
235        if (result.success) {
236            console.log('Device registered successfully:', result);
237            
238            // Start heartbeat to keep device active
239            deviceRegistration.startHeartbeat('[email protected]', 15);
240        } else {
241            console.error('Registration failed:', result.error);
242        }
243    });
244
245// Or use auto-register (checks if already registered recently)
246deviceRegistration.autoRegister('[email protected]', 123);
247*/
248
249// Export for use in modules
250if (typeof module !== 'undefined' && module.exports) {
251    module.exports = DeviceRegistration;
252}
253
254// Global access for direct script inclusion
255window.DeviceRegistration = DeviceRegistration;

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.