PageSourceSearch

https://noonlab.co.kr/noon-analytics/assets/tracker.js

js noonlab.co.kr collected 2026-10-06 14:03:35 UTC 7,174 bytes, 94 lines download raw bytes

1(function () {
2  'use strict';
3  if (window.NOONAnalytics) return;
4  var script = document.currentScript;
5  var base = new URL('../', script ? script.src : location.origin + '/noon-analytics/assets/tracker.js');
6  if (base.origin !== location.origin) return;
7  var endpoint = new URL('api/collect.php', base).href;
8  var preferencesOnly = !!(script && script.hasAttribute('data-preferences-only'));
9  var disabled = navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.globalPrivacyControl === true;
10  var current = null, timer = null, lastHeartbeat = 0, active = 0, lastTick = Date.now(), lastAction = Date.now(), maxScroll = 0, queue = Promise.resolve();
11
12  function day() { return new Date(Date.now() + 9 * 3600000).toISOString().slice(0, 10); }
13  function id() {
14    if (!window.crypto || !crypto.getRandomValues) return '';
15    var bytes = new Uint8Array(16); crypto.getRandomValues(bytes);
16    return Array.from(bytes, function (n) { return n.toString(16).padStart(2, '0'); }).join('');
17  }
18  function path() {
19    var p = location.pathname;
20    if (p === '/bbs/board.php') {
21      var q = new URLSearchParams(location.search), board = q.get('bo_table') || '';
22      if (!/^(project|digital_living|industrial_design|engineering|development|mold_design|graphic_design|packaing_design|notice)$/.test(board)) return '';
23      p += '?bo_table=' + board;
24      if (/^[1-9][0-9]{0,9}$/.test(q.get('wr_id') || '')) p += '&wr_id=' + q.get('wr_id');
25    } else if (/\/(?:adm|member|data|api|noon-analytics)\//.test(p) || /\/(?:login|register|write|password|memo|profile|search|download|link)[^/]*\.php$/.test(p)) return '';
26    return p;
27  }
28  function campaign(name) {
29    var v = (new URLSearchParams(location.search)).get(name) || '';
30    if (v.length > 80 || /@|https?:|\d{7,}|\d{2,4}[-. ]\d{3,4}[-. ]\d{4}/i.test(v)) return '';
31    return v;
32  }
33  function attribution() {
34    var host = ''; try { host = document.referrer ? new URL(document.referrer).hostname : ''; } catch (_) {}
35    var ua = navigator.userAgent;
36    return {ref_domain:host,source:campaign('utm_source'),medium:campaign('utm_medium'),campaign:campaign('utm_campaign'),device:/iPad|Tablet|PlayBook|Silk/i.test(ua) || (/Macintosh/.test(ua) && navigator.maxTouchPoints > 1) ? 'tablet' : /Mobi|Android|iPhone|iPod/i.test(ua) ? 'mobile' : 'desktop',browser:/Edg\//.test(ua) ? 'Edge' : /SamsungBrowser/.test(ua) ? 'Samsung' : /Firefox\//.test(ua) ? 'Firefox' : /Chrome\//.test(ua) ? 'Chrome' : /Safari\//.test(ua) ? 'Safari' : 'Other'};
37  }
38  function usable() { return !disabled && !preferencesOnly && !!path(); }
39  function context() {
40    var date = day();
41    if (!current || current.day !== date || current.path !== path()) {
42      // Ephemeral IDs live only in this page's JavaScript memory. No cookies,
43      // localStorage or sessionStorage identifiers are created.
44      var visit = id();
45      current = {day:date,vid:visit,sid:visit,page:id(),path:path(),registered:false};
46      active = 0; maxScroll = 0;
47    }
48    return current;
49  }
50  function tick() { var now = Date.now(); if (document.visibilityState === 'visible' && now - lastAction < 60000) active += Math.min(5000, Math.max(0,now - lastTick)); lastTick = now; }
51  function payload(ctx, type, extra) { return Object.assign({type:type,anonymous:true,day:ctx.day,vid:ctx.vid,sid:ctx.sid,page:ctx.page,path:ctx.path},extra || {}); }
52  async function post(body, beacon) {
53    if (!usable()) return false;
54    var text = JSON.stringify(body);
55    try {
56      if (beacon && navigator.sendBeacon) return navigator.sendBeacon(endpoint,new Blob([text],{type:'application/json'}));
57      var result = await fetch(endpoint,{method:'POST',credentials:'omit',headers:{'Content-Type':'application/json'},body:text,keepalive:true});
58      if (!result.ok) return false;
59      var data = await result.json(); return !!data.ok && !data.ignored;
60    } catch (_) { return false; }
61  }
62  function send(type, extra, beacon) {
63    if (!usable()) return;
64    var ctx = context(); tick();
65    var body = payload(ctx,type,extra);
66    if (type === 'heartbeat') { body.duration = Math.round(active / 1000); body.scroll = maxScroll; }
67    if (beacon && ctx.registered) { post(body,true); return; }
68    queue = queue.then(async function () {
69      if (!usable()) return;
70      if (!ctx.registered) ctx.registered = await post(payload(ctx,'page_view',attribution()),false);
71      if (ctx.registered && type !== 'page_view') await post(body,false);
72    }).catch(function () {});
73  }
74  function event(name, beacon) { send('event',{event:name,event_id:id()},beacon); }
75  function start() {
76    if (!usable() || timer) return;
77    lastAction = Date.now(); lastTick = Date.now(); send('page_view');
78    timer = setInterval(function () { tick(); if (document.visibilityState === 'visible' && Date.now() - lastAction < 60000 && Date.now() - lastHeartbeat >= 30000) { lastHeartbeat = Date.now(); send('heartbeat'); } },5000);
79  }
80  function stop() { clearInterval(timer); timer = null; current = null; }
81  function showSettings() { /* No consent banner: privacy-friendly aggregate analytics only. */ }
82  function setConsent() { /* Backward-compatible no-op. */ }
83
84  window.NOONAnalytics = {setConsent:setConsent,showSettings:showSettings,isAllowed:function(){return usable();},confirmed:function(kind){if(kind==='contact'||kind==='quote')event(kind+'_success_reported',true);}};
85  document.addEventListener('noon:conversion-confirmed',function(e){var kind=e.detail&&e.detail.kind;if(kind==='contact'||kind==='quote')event(kind+'_success_reported',true);});
86  ['pointerdown','keydown','scroll','touchstart'].forEach(function(name){document.addEventListener(name,function(){lastAction=Date.now();},{passive:true});});
87  document.addEventListener('scroll',function(){var total=document.documentElement.scrollHeight-innerHeight;maxScroll=Math.max(maxScroll,total>0?Math.min(100,Math.round((scrollY||0)/total*100)):100);},{passive:true});
88  document.addEventListener('visibilitychange',function(){tick();if(document.visibilityState==='hidden')send('heartbeat',null,true);else {lastAction=Date.now();lastTick=Date.now();}});
89  addEventListener('pagehide',function(){send('heartbeat',null,true);});
90  document.addEventListener('submit',function(e){var f=e.target;if(!f||f.tagName!=='FORM')return;var action=f.getAttribute('action')||'';if(location.pathname==='/sub02/sub01.php'||/write_update01\.php/.test(action))event('contact_intent',true);else if(location.pathname.indexOf('/development-consult/')===0||f.hasAttribute('data-noon-quote'))event('quote_intent',true);},true);
91  document.addEventListener('click',function(e){var a=e.target.closest?e.target.closest('a'):null;if(!a)return;var href=a.getAttribute('href')||'';if(/^tel:/i.test(href))event('phone_click',true);else if(/^mailto:/i.test(href))event('email_click',true);else if(/(?:\/sub02\/sub01\.php|\/development-consult\/)/.test(href))event('lead_cta_click',true);},true);
92  function init(){if(!preferencesOnly&&!path())return;if(disabled)stop();else if(!preferencesOnly)start();}
93  if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init,{once:true});else init();
94}());

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.