1/** 2 * WB Visitor Tracker SDK v1.0 3 */ 4(function (window, document) { 5 'use strict'; 6 7 var VERSION = 1; 8 var STORAGE_KEY = 'track-session-id'; 9 var SESSION_TIMEOUT = 30 * 60 * 1000; // 30ë¶ 10 var MAX_SESSION_TIME = 24 * 60 * 60 * 1000; // 24ìê° 11 12 // site_codeë³ pixel.gif ëë©ì¸ ë¼ì°í 13 var PIXEL_URLS = { 14 speakingmax: 'https://track.speakingmaxapp.com/pixel.gif', 15 maxai: 'https://track.maxaiapp.com/pixel.gif', 16 ra: 'https://ra-track.speakingmaxapp.com/pixel.gif', 17 weaversbrain: 'https://track.speakingmaxapp.com/pixel.gif', 18 speakingdom: 'https://track.speakingmaxapp.com/pixel.gif' 19 }; 20 21 var VALID_SITES = Object.keys(PIXEL_URLS); 22 23 // --------------------------------------------------------------- 24 // ì í¸ë¦¬í° 25 // --------------------------------------------------------------- 26 27 function generateUUID() { 28 return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 29 var r = (Math.random() * 16) | 0; 30 return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16); 31 }); 32 } 33 34 function now() { 35 return new Date().getTime(); 36 } 37 38 // --------------------------------------------------------------- 39 // ì¸ì ê´ë¦¬ 40 // --------------------------------------------------------------- 41 42 function getSession() { 43 var stored = null; 44 try { stored = localStorage.getItem(STORAGE_KEY); } catch (e) { /* private browsing */ } 45 46 var ts = now(); 47 var pattern = /^wb(\d+)\.(\d+)\.[0-9a-f]{32}\.(\d+)$/; 48 49 if (stored && pattern.test(stored)) { 50 var parts = stored.split('.'); 51 var createdAt = Number(parts[1]); 52 var expireAt = Number(parts[3]); 53 54 if (ts <= expireAt && (createdAt + MAX_SESSION_TIME) > ts) { 55 parts[3] = String(ts + SESSION_TIMEOUT); 56 var renewed = parts.join('.'); 57 try { localStorage.setItem(STORAGE_KEY, renewed); } catch (e) {} 58 return parseSession(renewed); 59 } 60 } 61 62 var newId = 'wb' + VERSION + '.' + ts + '.' + generateUUID() + '.' + (ts + SESSION_TIMEOUT); 63 try { localStorage.setItem(STORAGE_KEY, newId); } catch (e) {} 64 return parseSession(newId); 65 } 66 67 function parseSession(raw) { 68 var parts = raw.split('.'); 69 return { 70 trackingId: raw, 71 sessionId: parts[0] + '.' + parts[1] + '.' + parts[2], 72 expireAt: Number(parts[3]) 73 }; 74 } 75 76 // --------------------------------------------------------------- 77 // íê²½ íë³ 78 // --------------------------------------------------------------- 79 80 function detectEnv() { 81 var host = window.location.hostname || ''; 82 if (host.indexOf('local') !== -1) return 'dev'; 83 if (host.indexOf('dev') !== -1) return 'dev'; 84 if (host.indexOf('qa') !== -1) return 'qa'; 85 return 'prod'; 86 } 87 88 // --------------------------------------------------------------- 89 // ëë°ì´ì¤ íë³ 90 // --------------------------------------------------------------- 91 92 function detectDevice() { 93 var ua = navigator.userAgent || ''; 94 if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(ua)) { 95 return 'MO'; 96 } 97 return 'PC'; 98 } 99 100 // --------------------------------------------------------------- 101 // page_name ìë ì¶ì¶ 102 // --------------------------------------------------------------- 103 104 function extractPageName() { 105 var path = window.location.pathname || '/'; 106 // ì í/íí ì¬ëì ì ê±° í, ì¬ëì â ì¸ëì¤ì½ì´ 107 var name = path.replace(/^\/|\/$/g, '').replace(/\//g, '_'); 108 return name || 'index'; 109 } 110 111 // --------------------------------------------------------------- 112 // UTM íë¼ë¯¸í° ì¶ì¶ 113 // --------------------------------------------------------------- 114 115 function getUtmParams() { 116 var params = {}; 117 try { 118 var sp = new URL(window.location.href).searchParams; 119 var utmKeys = ['utm_source', 'utm_campaign', 'utm_medium', 'utm_term', 'utm_content']; 120 for (var i = 0; i < utmKeys.length; i++) { 121 var val = sp.get(utmKeys[i]); 122 if (val) params[utmKeys[i]] = val; 123 } 124 } catch (e) {} 125 return params; 126 } 127 128 // --------------------------------------------------------------- 129 // pixel.gif GET ì ì¡ 130 // --------------------------------------------------------------- 131 132 function sendPixel(baseUrl, params) { 133 var qs = []; 134 for (var key in params) { 135 if (params.hasOwnProperty(key) && params[key] !== '' && params[key] != null) { 136 qs.push(encodeURIComponent(key) + '=' + encodeURIComponent(params[key])); 137 } 138 } 139 var url = baseUrl + '?' + qs.join('&'); 140 new Image().src = url; 141 } 142 143 // --------------------------------------------------------------- 144 // ì´ë²¤í¸ ë¹ë 145 // --------------------------------------------------------------- 146 147 function buildParams(eventName, session, siteCode, extra) { 148 var utm = getUtmParams(); 149 var pageName = (extra && extra.page_name) ? extra.page_name : extractPageName(); 150 151 var params = { 152 track_type: siteCode, 153 env: detectEnv(), 154 platform: detectDevice(), 155 page_name: pageName, 156 event_name: eventName, 157 url: window.location.href, 158 referrer: document.referrer || '', 159 session_id: session.sessionId 160 }; 161 162 // UTM íë¼ë¯¸í° 163 var utmKeys = ['utm_source', 'utm_campaign', 'utm_medium', 'utm_term', 'utm_content']; 164 for (var i = 0; i < utmKeys.length; i++) { 165 if (utm[utmKeys[i]]) { 166 params[utmKeys[i]] = utm[utmKeys[i]]; 167 } 168 } 169 170 // extraìì page_name ì¸ì ì¶ê° íë¼ë¯¸í° ë³í© 171 if (extra && typeof extra === 'object') { 172 for (var key in extra) { 173 if (extra.hasOwnProperty(key) && key !== 'page_name') { 174 params[key] = extra[key]; 175 } 176 } 177 } 178 179 return params; 180 } 181 182 // --------------------------------------------------------------- 183 // Public API 184 // --------------------------------------------------------------- 185 186 var WB_TRACKER = { 187 _config: { 188 pixelUrl: '', 189 site: '', 190 initialized: false 191 }, 192 193 /** 194 * SDK ì´ê¸°í ë° íì´ì§ë·° ìë ì ì¡ 195 * @param {string} siteCode - weaversbrain|speakingmax|maxai|speakingdom|ra 196 * @param {object} [options] - { pixelUrl: 'https://...' } (ì í, ì¤ë²ë¼ì´ëì©) 197 */ 198 init: function (siteCode, options) { 199 if (this._config.initialized) return; 200 201 if (VALID_SITES.indexOf(siteCode) === -1) { 202 if (typeof console !== 'undefined') { 203 console.warn('[wbTracker] Invalid site code: ' + siteCode); 204 } 205 return; 206 } 207 208 this._config.site = siteCode;
209 this._config.pixelUrl = (options && options.pixelUrl) ? options.pixelUrl : PIXEL_URLS[siteCode]; 210 this._config.initialized = true; 211 212 this.track('page_view'); 213 }, 214 215 /** 216 * 커ì¤í ì´ë²¤í¸ ì ì¡ 217 * @param {string} eventName - ì´ë²¤í¸ íì (page_view, button_click, ...) 218 * @param {object} [extra] - ì¶ê° ë°ì´í° (page_name ë±) 219 */ 220 track: function (eventName, extra) { 221 if (!this._config.initialized) return; 222 223 var session = getSession(); 224 var params = buildParams(eventName, session, this._config.site, extra); 225 sendPixel(this._config.pixelUrl, params); 226 } 227 }; 228 229 window.wbTracker = WB_TRACKER; 230 231})(window, document);
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.