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.