1// ad_audit.js 2 3$(function () { 4 5 const SAMPLE_RATE = 0.001; // 0.1 = 10%, 0.01 = 1% 6 const USE_DAILY_LIMIT = true; 7 8 const LOG_URL = 'https://gall.dcinside.com/dcad/ad_audit_log'; 9 const AUDIT_KEY = 'DC_AUDIT_KEY_2026'; 10 11 const FIRST_WAIT_TIME = 3000; 12 const RETRY_WAIT_TIME = 5000; 13 14 const today = new Date().toISOString().slice(0, 10); 15 const dailyKey = 'ad_audit_checked_' + location.hostname + '_' + today; 16 17 if (USE_DAILY_LIMIT && localStorage.getItem(dailyKey)) { 18 return; 19 } 20 21 if (Math.random() > SAMPLE_RATE) { 22 return; 23 } 24 25 if (USE_DAILY_LIMIT) { 26 localStorage.setItem(dailyKey, 'Y'); 27 } 28 29 const AD_CONFIGS = [ 30 { 31 ad_type: 'kakao', 32 script_keyword: 'ba.min.js', 33 selector: '.kakao_ad_area', 34 unit_attr: 'data-ad-unit', 35 width_attr: 'data-ad-width', 36 height_attr: 'data-ad-height', 37 require_unit: true 38 }, 39 { 40 ad_type: 'google_adsense_old', 41 script_keyword: 'show_ads.js', 42 selector: '.google_ad_area', 43 unit_attr: 'data-ad-unit', 44 width_attr: 'data-ad-width', 45 height_attr: 'data-ad-height', 46 require_unit: true 47 }, 48 { 49 ad_type: 'google_adsense_new', 50 script_keyword: 'adsbygoogle', 51 selector: '.adsbygoogle', 52 unit_attr: 'data-ad-slot', 53 width_attr: null, 54 height_attr: null, 55 require_unit: true 56 }, 57 { 58 ad_type: 'netinsight_criteo', 59 script_keyword: 'ad.xc.netinsight.co.kr', 60 selector: 'div[id^="criteo-"]', 61 unit_attr: 'id', 62 width_attr: null, 63 height_attr: null, 64 require_unit: true 65 }, 66 { 67 ad_type: 'adnmore_toast', 68 script_keyword: 'adnmore.co.kr', 69 selector: 'div[id^="foin_"]', 70 unit_attr: 'id', 71 width_attr: null, 72 height_attr: null, 73 require_unit: true 74 } 75 ]; 76 77 const getScriptInfo = (keyword) => { 78 const result = { 79 exists: false, 80 src: '' 81 }; 82 83 $('script').each(function () { 84 const src = $(this).attr('src') || ''; 85 86 if (src.indexOf(keyword) !== -1) { 87 result.exists = true; 88 result.src = src; 89 return false; 90 } 91 }); 92 93 return result; 94 }; 95 96 const getAdSize = ($ad, config) => { 97 let width = 0; 98 let height = 0; 99 100 if (config.width_attr) { 101 width = parseInt($ad.attr(config.width_attr), 10) || 0; 102 } else { 103 width = $ad.width() || parseInt($ad.attr('width'), 10) || 0; 104 } 105 106 if (config.height_attr) { 107 height = parseInt($ad.attr(config.height_attr), 10) || 0; 108 } else { 109 height = $ad.height() || parseInt($ad.attr('height'), 10) || 0; 110 } 111 112 return { 113 width, 114 height 115 }; 116 }; 117 118 const getVisibleIframe = ($ad) => { 119 return $ad.find('iframe').filter(function () { 120 const $iframe = $(this); 121 122 const width = 123 $iframe.width() || 124 parseInt($iframe.attr('width'), 10) || 125 0; 126 127 const height = 128 $iframe.height() || 129 parseInt($iframe.attr('height'), 10) || 130 0; 131 132 if (width <= 0 || height <= 0) { 133 return false; 134 } 135 136 if ($iframe.css('display') === 'none') { 137 return false; 138 } 139 140 return true; 141 }); 142 }; 143 144 const sendAuditLog = (data) => { 145 $.ajax({
146 url: LOG_URL, 147 type: 'POST', 148 dataType: 'json', 149 data, 150 timeout: 3000, 151 crossDomain: true, 152 error: () => { 153 console.log('[AD AUDIT] ë¡ê·¸ ì ì¥ ì¤í¨'); 154 } 155 }); 156 }; 157 158 const processAudit = (config, scriptInfo, $ad, index, retry) => { 159 160 const adUnit = config.unit_attr 161 ? ($ad.attr(config.unit_attr) || '') 162 : ''; 163 164 // ad_unit ìë ë´ë¶ DOMì ì ì¥íì§ ìì 165 if (config.require_unit && !adUnit) { 166 return; 167 } 168 169 const adVisible = $ad.is(':visible') ? 'Y' : 'N'; 170 171 const $iframe = getVisibleIframe($ad); 172 const iframeExists = $iframe.length > 0; 173 174 const adSize = getAdSize($ad, config); 175 176 const iframeWidth = iframeExists 177 ? ( 178 $iframe.first().width() || 179 parseInt($iframe.first().attr('width'), 10) || 180 0 181 ) 182 : 0; 183 184 const iframeHeight = iframeExists 185 ? ( 186 $iframe.first().height() || 187 parseInt($iframe.first().attr('height'), 10) || 188 0 189 ) 190 : 0; 191 192 const adStatus = $ad.attr('data-ad-status') || ''; 193 194 let auditStatus = 'success'; 195 196 if (!scriptInfo.exists) { 197 auditStatus = 'script_fail'; 198 } else if (!iframeExists) { 199 auditStatus = 'render_fail'; 200 } else if (adVisible === 'N') { 201 auditStatus = 'hidden'; 202 } 203 204 if (auditStatus === 'render_fail' && retry === false) { 205 console.log('[AD AUDIT RETRY]', config.ad_type); 206 207 setTimeout(() => { 208 processAudit( 209 config, 210 scriptInfo, 211 $ad, 212 index, 213 true 214 ); 215 }, RETRY_WAIT_TIME); 216 217 return; 218 } 219 220 const result = { 221 audit_key: AUDIT_KEY, 222 223 ad_type: config.ad_type, 224 domain: location.hostname, 225 page_url: location.href, 226 user_agent: navigator.userAgent, 227 228 ad_index: index, 229 ad_unit: adUnit, 230 231 ad_width: adSize.width, 232 ad_height: adSize.height, 233 234 script_exists: scriptInfo.exists ? 'Y' : 'N', 235 script_src: scriptInfo.src, 236 237 iframe_exists: iframeExists ? 'Y' : 'N', 238 iframe_width: iframeWidth, 239 iframe_height: iframeHeight, 240 241 ad_status: adStatus, 242 ad_visible: adVisible, 243 audit_status: auditStatus 244 }; 245 246 console.log('[AD AUDIT]', result); 247 248 sendAuditLog(result); 249 }; 250 251 setTimeout(() => { 252 253 $.each(AD_CONFIGS, (_, config) => { 254 255 const scriptInfo = getScriptInfo(config.script_keyword); 256 const $targets = $(config.selector); 257 258 if ($targets.length <= 0) { 259 const result = { 260 audit_key: AUDIT_KEY, 261 262 ad_type: config.ad_type, 263 domain: location.hostname, 264 page_url: location.href, 265 user_agent: navigator.userAgent, 266 267 ad_index: 0, 268 ad_unit: '', 269 270 ad_width: 0, 271 ad_height: 0, 272 273 script_exists: scriptInfo.exists ? 'Y' : 'N', 274 script_src: scriptInfo.src, 275 276 iframe_exists: 'N', 277 iframe_width: 0, 278 iframe_height: 0, 279 280 ad_status: '', 281 ad_visible: 'N', 282 283 audit_status: scriptInfo.exists 284 ? 'selector_fail' 285 : 'script_fail' 286 }; 287 288 console.log('[AD AUDIT FAIL]', result); 289 290 sendAuditLog(result); 291 292 return; 293 } 294 295 $targets.each(function (index) { 296 processAudit( 297 config, 298 scriptInfo, 299 $(this), 300 index, 301 false 302 ); 303 }); 304 305 }); 306 307 }, FIRST_WAIT_TIME); 308 309});
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.