1(function () { 2 'use strict'; 3 4 var EVENT_IDS = [800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814]; 5 var EXCLUDE_USER_AGENTS = ['bot', 'uptimecrawler']; 6 var BREAKPOINT_DESKTOP = 1200; 7 var BREAKPOINT_TABLET = 720; 8 var HOST = 'delivery.momentummedia.com.au'; 9 var DELIVERY_HOST_MAP = { 10 'e-10860.adzerk.net': HOST, 11 'static.adzerk.net': 's.zkcdn.net' 12 }; 13 var IMAGE_PROXY_BASE = 'https://kevel.momentummedia.com.au/proxy/'; 14 var SEGMENT_URL = '/index.php?option=com_ajax&plugin=kevelsegment&format=json'; 15 var EVENT_INTERVALS = [5, 10, 15, 20, 30, 45, 60, 75, 90, 110, 130, 150, 180, 210, 240]; 16 17 var zoneCounter = 1; 18 var client = null; 19 var debugStore = []; 20 21 function getBreakpointLabel() { 22 var w = window.innerWidth; 23 if (w >= BREAKPOINT_DESKTOP) return 'desktop'; 24 if (w >= BREAKPOINT_TABLET) return 'tablet'; 25 return 'mobile'; 26 } 27 28 function extractDecisions(response, divIds, count) { 29 var result = []; 30 if (!response || !response.decisions) return result; 31 var decisions = response.decisions; 32 33 if (divIds) {
34 Object.keys(decisions).forEach(function (key) { 35 if (decisions[key] && decisions[key][0]) { 36 result.push(decisions[key][0]); 37 } 38 }); 39 } else if (count > 1) { 40 var list = decisions.div0; 41 if (Array.isArray(list)) { 42 result = list; 43 } 44 } else { 45 if (decisions.div0 && decisions.div0[0]) { 46 result.push(decisions.div0[0]); 47 } 48 } 49 return result; 50 } 51 52 // -- Bot guard -- 53 function isBot() { 54 var ua = navigator.userAgent.toLowerCase(); 55 return EXCLUDE_USER_AGENTS.some(function (p) { return ua.indexOf(p) !== -1; }); 56 } 57 58 // -- User key (from utm_emailID URL param â localStorage) -- 59 function initUserKey() { 60 var params = new URLSearchParams(window.location.search); 61 var emailId = params.get('utm_emailID') || ''; 62 if (emailId) { 63 localStorage.setItem('kevel_user_key', emailId); 64 } 65 return emailId || localStorage.getItem('kevel_user_key') || ''; 66 } 67 68 function getUserKey() { 69 return localStorage.getItem('kevel_user_key') || ''; 70 } 71 72 // -- Segments (fetched only when kevel_user_key exists, stored in localStorage) -- 73 function initSegments(userKey) { 74 if (!userKey) return; 75 76 var payload = { name: 'user', email: userKey }; 77 fetch(SEGMENT_URL, { 78 method: 'POST', 79 body: JSON.stringify(payload) 80 }) 81 .then(function (res) { return res.json(); }) 82 .then(function (data) { 83 if (Array.isArray(data) && data.length > 0) { 84 localStorage.setItem('kevel-segment', data.join(',')); 85 } 86 }) 87 .catch(function () {}); 88 } 89 90 // -- Breakpoint detection -- 91 function getAdTypes(element) { 92 var w = window.innerWidth; 93 if (w >= BREAKPOINT_DESKTOP) return parseIntArray(element.dataset.kevelDesktopTypes); 94 if (w >= BREAKPOINT_TABLET) return parseIntArray(element.dataset.kevelTabletTypes); 95 return parseIntArray(element.dataset.kevelMobileTypes); 96 } 97 98 function parseIntArray(str) { 99 if (!str) return []; 100 return str.split(',').map(function (s) { return parseInt(s, 10); }); 101 } 102 103 // -- SDK client (singleton) -- 104 function getClient(networkId, siteId) { 105 if (!client) { 106 client = new AdzerkDecisionSdk.Client({ 107 networkId: networkId, 108 siteId: siteId, 109 host: HOST 110 }); 111 } 112 return client; 113 } 114 115 // -- Build Decision request -- 116 function buildRequest(element) { 117 var dataset = element.dataset; 118 var adTypes = getAdTypes(element); 119 var zoneIds = parseIntArray(dataset.kevelZoneIds); 120 var count = parseInt(dataset.kevelCount, 10) || 1; 121 var keyword = dataset.kevelKeyword || ''; 122 var tags = dataset.kevelTags || ''; 123 124 var keywordsArray = []; 125 var segment = localStorage.getItem('kevel-segment'); 126 if (segment) { 127 keywordsArray = segment.split(','); 128 } 129 if (keyword) { 130 keywordsArray.push(keyword); 131 } 132 133 var divIds = dataset.kevelDivIds; 134 var placements; 135 if (divIds) { 136 var ids = divIds.split(','); 137 placements = ids.map(function (id, i) { 138 return { 139 divName: '#' + id.trim(), 140 adTypes: adTypes, 141 zoneIds: [zoneIds[i % zoneIds.length]], 142 properties: { url: location.pathname, tags: tags }, 143 eventIds: EVENT_IDS 144 }; 145 }); 146 } else { 147 placements = [{ 148 adTypes: adTypes, 149 zoneIds: zoneIds, 150 count: count, 151 properties: { url: location.pathname, tags: tags }, 152 eventIds: EVENT_IDS 153 }]; 154 } 155 156 return { 157 placements: placements, 158 enableBotFiltering: true, 159 user: { key: getUserKey() }, 160 keywords: keywordsArray,
161 ip: window.CLIENT_IP || null 162 }; 163 } 164 165 // -- URL rewriting (branded domains) -- 166 function rewriteUrls(html) { 167 if (!html) return html; 168 Object.keys(DELIVERY_HOST_MAP).forEach(function (from) { 169 html = html.split(from).join(DELIVERY_HOST_MAP[from]); 170 }); 171 return html; 172 } 173 174 // -- Proxy image URL -- 175 function proxyImageUrl(imgUrl) { 176 var parts = imgUrl.split('/Advertisers/'); 177 if (parts.length < 2) return imgUrl; 178 var fileNameParts = parts[1].split('.'); 179 return IMAGE_PROXY_BASE + '?id=' + fileNameParts[0] + '&format=' + fileNameParts[1]; 180 } 181 182 // -- Render single decision -- 183 function renderDecision(decision, targetEl) { 184 var content = decision.contents[0]; 185 var impressionPixel = '<img height="0" width="0" src="' + decision.impressionUrl 186 + '" style="position:absolute;display:none;">'; 187 188 if (content.type === 'raw' || content.type === 'html') { 189 var frameId = 'kevel-frame-' + decision.flightId + '-' + zoneCounter; 190 var w = parseInt(content.data.width, 10); 191 var h = parseInt(content.data.height, 10); 192 targetEl.innerHTML = rewriteUrls( 193 '<iframe id="' + frameId + '" frameborder="0" scrolling="no" width="' 194 + w + '" height="' + h + '"></iframe>' + impressionPixel 195 ); 196 var doc = document.getElementById(frameId).contentWindow.document; 197 doc.open(); 198 doc.write(rewriteUrls('<body style="margin:0;">' + content.body + '</body>')); 199 doc.close(); 200 } else { 201 var body = content.body || ''; 202 if (content.data && content.data.imageUrl) { 203 body = body.split(content.data.imageUrl).join(proxyImageUrl(content.data.imageUrl)); 204 } 205 targetEl.innerHTML = rewriteUrls(body) + impressionPixel; 206 } 207 208 trackViewability(targetEl, decision.events); 209 zoneCounter++; 210 } 211 212 // -- Viewability tracking (IntersectionObserver + setTimeout) -- 213 function trackViewability(element, events) { 214 if (!events || events.length === 0) return; 215 216 var eventIndex = 0; 217 var observer = new IntersectionObserver(function (entries) { 218 if (!entries[0].isIntersecting) return; 219 220 EVENT_INTERVALS.forEach(function (secs, i) { 221 if (i >= events.length) return; 222 setTimeout(function () { 223 if (eventIndex <= i) { 224 firePixel(rewriteUrls(events[i].url), element); 225 eventIndex = i + 1; 226 } 227 }, secs * 1000); 228 }); 229 230 observer.disconnect(); 231 }, { threshold: 0 }); 232 233 observer.observe(element); 234 } 235 236 function firePixel(url, container) { 237 var img = document.createElement('img'); 238 img.src = url; 239 img.style.display = 'none'; 240 img.style.position = 'absolute'; 241 img.width = 0; 242 img.height = 0; 243 container.appendChild(img); 244 } 245 246 // -- Multi-creative handler (promoted content) -- 247 function renderMultiCreative(decisions, targetEl) { 248 var html = ''; 249 decisions.forEach(function (decision) { 250 var content = decision.contents[0]; 251 var impressionPixel = '<img height="0" width="0" src="' + decision.impressionUrl 252 + '" style="position:absolute;display:none;">'; 253 if (content.type === 'html') { 254 html += '<div class="momentum-promotedcontent-item">' 255 + rewriteUrls(content.body) + impressionPixel + '</div>'; 256 } 257 }); 258 targetEl.innerHTML = html; 259 } 260 261 // -- Slot event dispatch -- 262 function dispatchSlotEvent(element, name, detail) { 263 element.dispatchEvent(new CustomEvent(name, { 264 bubbles: true, 265 detail: detail 266 })); 267 } 268 269 // -- Placeholder cleanup -- 270 function clearPlaceholder(element) { 271 var ph = element.querySelector('.kevel-ph'); 272 if (ph) ph.parentNode.removeChild(ph); 273 } 274 275 // -- Process a single kevel-zone element -- 276 function processElement(element) { 277 var dataset = element.dataset; 278 var networkId = parseInt(dataset.kevelNetworkId, 10); 279 var siteId = parseInt(dataset.kevelSiteId, 10); 280 var count = parseInt(dataset.kevelCount, 10) || 1; 281 var divIds = dataset.kevelDivIds; 282 283 var adTypes = getAdTypes(element); 284 if (adTypes.length === 0) { 285 clearPlaceholder(element); 286 element.classList.add('hidden'); 287 return; 288 } 289 290 var adzerk = getClient(networkId, siteId); 291 var request = buildRequest(element); 292 293 var entry = {
294 elementId: element.id, 295 classes: element.className, 296 timestamp: Date.now(), 297 breakpoint: getBreakpointLabel(), 298 request: request, 299 response: null, 300 decisions: [], 301 status: 'pending', 302 error: null 303 }; 304 debugStore.push(entry); 305 306 adzerk.decisions.get(request).then(function (response) { 307 entry.response = response; 308 entry.decisions = extractDecisions(response, divIds, count); 309 entry.status = entry.decisions.length > 0 ? 'rendered' : 'empty'; 310 311 if (divIds) { 312 var decisions = response.decisions; 313 314 Object.keys(decisions).forEach(function (key) { 315 var newKey = key; 316 var targetEl = document.querySelector(key); 317 318 if (/-variant-\d+$/.test(key)) { 319 newKey = key.replace(/-variant-\d+$/, ''); 320 } 321 322 if (decisions[key] && decisions[key][0] && (!decisions[newKey] || !decisions[newKey][0])) { 323 targetEl = document.querySelector(newKey); 324 decisions[newKey] = decisions[key]; 325 } 326 327 328 if (targetEl && decisions[key] && decisions[key][0]) { 329 renderDecision(decisions[key][0], targetEl); 330 } else if (targetEl) { 331 clearPlaceholder(targetEl); 332 } 333 }); 334 clearPlaceholder(element); 335 } else if (count > 1) { 336 var list = response.decisions.div0; 337 if (list && list.length > 0) { 338 renderMultiCreative(list, element); 339 } else { 340 clearPlaceholder(element); 341 element.classList.add('hidden'); 342 } 343 } else { 344 var decision = response.decisions.div0 && response.decisions.div0[0]; 345 if (decision) { 346 renderDecision(decision, element); 347 } else { 348 clearPlaceholder(element); 349 element.classList.add('hidden'); 350 } 351 } 352 353 if (entry.status === 'rendered') { 354 dispatchSlotEvent(element, 'kevel:loaded', { 355 status: 'rendered', 356 decisions: entry.decisions, 357 response: response, 358 breakpoint: entry.breakpoint 359 }); 360 } else { 361 dispatchSlotEvent(element, 'kevel:empty', { 362 status: 'empty', 363 breakpoint: entry.breakpoint 364 }); 365 } 366 367 }).catch(function (err) { 368 entry.status = 'error'; 369 entry.error = err.message || String(err); 370 clearPlaceholder(element); 371 element.classList.add('hidden'); 372 dispatchSlotEvent(element, 'kevel:error', { 373 status: 'error', 374 error: entry.error, 375 breakpoint: entry.breakpoint 376 }); 377 }); 378 } 379 380 // -- Debug panel -- 381 var PANEL_ID = 'kevel-debug-panel'; 382 var DEBUG_OUTLINE_CLASS = 'kevel-debug-outline'; 383 384 var panelStyles = { 385 position: 'fixed', 386 bottom: '12px', 387 right: '12px', 388 width: '420px', 389 maxHeight: '80vh', 390 overflow: 'auto', 391 background: '#1e1e2e', 392 color: '#cdd6f4', 393 fontFamily: 'monospace', 394 fontSize: '12px', 395 border: '1px solid #45475a', 396 borderRadius: '8px', 397 zIndex: '999999', 398 boxShadow: '0 8px 32px rgba(0,0,0,0.5)', 399 lineHeight: '1.5' 400 }; 401 402 function applyStyles(el, styles) { 403 Object.keys(styles).forEach(function (k) { el.style[k] = styles[k]; }); 404 } 405 406 function el(tag, styles, text) { 407 var node = document.createElement(tag); 408 if (styles) applyStyles(node, styles); 409 if (text !== undefined) node.textContent = text; 410 return node; 411 } 412 413 function statusColor(status) { 414 if (status === 'rendered') return '#a6e3a1'; 415 if (status === 'pending') return '#f9e2af'; 416 return '#f38ba8'; 417 } 418 419 function statusIcon(status) { 420 if (status === 'rendered') return '\u2713'; 421 if (status === 'pending') return '\u25CB'; 422 return '\u2717'; 423 } 424 425 function slotLabel(entry) { 426 var name = entry.elementId; 427 return name; 428 } 429 430 function truncate(str, max) { 431 if (!str) return '-'; 432 return str.length > max ? str.substring(0, max) + '...' : str; 433 } 434 435 function buildHeader(panel, onClose) { 436 var header = el('div', { 437 display: 'flex', justifyContent: 'space-between', alignItems: 'center', 438 padding: '10px 14px', borderBottom: '1px solid #45475a', background: '#181825' 439 }); 440 header.appendChild(el('span', { fontWeight: 'bold', fontSize: '14px', color: '#89b4fa' }, 'Kevel Debug')); 441 var closeBtn = el('span', { 442 cursor: 'pointer', fontSize: '16px', color: '#6c7086', padding: '0 4px' 443 }, '\u2715'); 444 closeBtn.addEventListener('click', onClose); 445 header.appendChild(closeBtn); 446 panel.appendChild(header); 447 } 448 449 function buildSummary(panel) { 450 var wrap = el('div', { padding: '8px 14px', borderBottom: '1px solid #313244', fontSize: '11px', color: '#a6adc8' }); 451 var lines = [ 452 'Page: ' + location.pathname, 453 'Slots: ' + debugStore.length + ' | Breakpoint: ' + getBreakp
453ointLabel(), 454 'User key: ' + (getUserKey() || '(none)') + ' | IP: ' + (window.CLIENT_IP || '(none)'), 455 'Segments: ' + (localStorage.getItem('kevel-segment') || '(none)') 456 ]; 457 lines.forEach(function (line) { 458 wrap.appendChild(el('div', { padding: '1px 0' }, line)); 459 }); 460 panel.appendChild(wrap); 461 } 462 463 function buildSlotList(panel) { 464 var list = el('div', { padding: '6px 0' }); 465 466 if (debugStore.length === 0) { 467 list.appendChild(el('div', { padding: '12px 14px', color: '#6c7086', fontStyle: 'italic' }, 'No ad slots processed yet.')); 468 panel.appendChild(list); 469 return; 470 } 471 472 debugStore.forEach(function (entry, idx) { 473 var row = el('div', { 474 padding: '6px 14px', cursor: 'pointer', display: 'flex', 475 alignItems: 'center', gap: '8px', borderBottom: '1px solid #313244' 476 }); 477 478 row.addEventListener('mouseenter', function () { row.style.background = '#313244'; }); 479 row.addEventListener('mouseleave', function () { row.style.background = 'transparent'; }); 480 481 var icon = el('span', { color: statusColor(entry.status), flexShrink: '0' }, statusIcon(entry.status)); 482 var name = el('span', { flex: '1', color: '#cdd6f4' }, slotLabel(entry)); 483 var badge = el('span', { color: statusColor(entry.status), fontSize: '11px' }, entry.status); 484 row.appendChild(icon); 485 row.appendChild(name); 486 row.appendChild(badge); 487 488 if (entry.decisions.length > 0) { 489 var fl = el('span', { color: '#6c7086', fontSize: '11px', marginLeft: '6px' }, 490 'FL:' + entry.decisions[0].flightId); 491 row.appendChild(fl); 492 } 493 494 row.addEventListener('click', function () { 495 renderDetailView(panel, entry, idx); 496 }); 497 498 list.appendChild(row); 499 }); 500 501 panel.appendChild(list); 502 } 503 504 function renderDetailView(panel, entry, idx) { 505 while (panel.children.length > 1) { 506 panel.removeChild(panel.lastChild); 507 } 508 509 var backRow = el('div', { 510 padding: '8px 14px', cursor: 'pointer', borderBottom: '1px solid #45475a', 511 color: '#89b4fa', fontSize: '12px' 512 }, '\u25C2 Back'); 513 backRow.addEventListener('click', function () { 514 while (panel.children.length > 1) { 515 panel.removeChild(panel.lastChild); 516 } 517 buildSummary(panel); 518 buildSlotList(panel); 519 }); 520 panel.appendChild(backRow); 521 522 var body = el('div', { padding: '10px 14px' }); 523 524 body.appendChild(sectionTitle(slotLabel(entry) + ' (#' + entry.elementId + ')')); 525 body.appendChild(kvLine('Status', entry.status, statusColor(entry.status))); 526 body.appendChild(kvLine('Time', new Date(entry.timestamp).toLocaleTimeString())); 527 if (entry.error) { 528 body.appendChild(kvLine('Error', entry.error, '#f38ba8')); 529 } 530 531 if (entry.decisions.length > 0) { 532 entry.decisions.forEach(function (d, di) { 533 body.appendChild(sectionTitle('Decision' + (entry.decisions.length > 1 ? ' ' + (di + 1) : ''))); 534 body.appendChild(kvLine('Flight ID', d.flightId)); 535 body.appendChild(kvLine('Campaign ID', d.campaignId)); 536 body.appendChild(kvLine('Ad ID', d.adId)); 537 body.appendChild(kvLine('Creative ID', d.creativeId)); 538 if (d.contents && d.contents[0]) { 539 var c = d.contents[0]; 540 body.appendChild(kvLine('Content type', c.type)); 541 if (c.data) { 542 if (c.data.width && c.data.height) { 543 body.appendChild(kvLine('Dimensions', c.data.width + ' \u00D7 ' + c.data.height)); 544 } 545 if (c.data.imageUrl) { 546 body.appendChild(kvLine('Image URL', truncate(c.data.imageUrl, 50))); 547 } 548 } 549 } 550 body.appendChild(kvLine('Click URL', truncate(d.clickUrl, 50))); 551 body.appendChild(kvLine('Impression URL', truncate(d.impressionUrl, 50))); 552 553 if (d.events && d.events.length > 0) { 554 body.appendChild(sectionTitle('Events (' + d.events.length + ')'));
555 d.events.forEach(function (evt, ei) { 556 var secs = EVENT_INTERVALS[ei] !== undefined ? EVENT_INTERVALS[ei] + 's' : ei; 557 body.appendChild(kvLine(secs, truncate(evt.url, 50))); 558 }); 559 } 560 }); 561 } 562 563 var p = entry.request.placements[0]; 564 body.appendChild(sectionTitle('Request')); 565 body.appendChild(kvLine('Zone IDs', p.zoneIds ? p.zoneIds.join(', ') : '-')); 566 body.appendChild(kvLine('Ad types', p.adTypes ? p.adTypes.join(', ') : '-')); 567 body.appendChild(kvLine('Keywords', entry.request.keywords.length > 0 ? entry.request.keywords.join(', ') : '-')); 568 body.appendChild(kvLine('Tags', (p.properties && p.properties.tags) || '-')); 569 body.appendChild(kvLine('Count', p.count || 1)); 570 body.appendChild(kvLine('IP', entry.request.ip || '-')); 571 body.appendChild(kvLine('User key', entry.request.user.key || '-')); 572 573 body.appendChild(sectionTitle('Raw')); 574 body.appendChild(jsonToggle('Request JSON', entry.request)); 575 body.appendChild(jsonToggle('Response JSON', entry.response)); 576 577 panel.appendChild(body); 578 } 579 580 function sectionTitle(text) { 581 return el('div', { 582 padding: '8px 0 4px', marginTop: '6px', borderTop: '1px solid #313244', 583 color: '#89b4fa', fontWeight: 'bold', fontSize: '11px', textTransform: 'uppercase' 584 }, text); 585 } 586 587 function kvLine(label, value, valueColor) { 588 var row = el('div', { display: 'flex', padding: '1px 0', gap: '8px' }); 589 row.appendChild(el('span', { color: '#6c7086', minWidth: '110px', flexShrink: '0' }, label)); 590 row.appendChild(el('span', { color: valueColor || '#cdd6f4', wordBreak: 'break-all' }, 591 value !== null && value !== undefined ? String(value) : '-')); 592 return row; 593 } 594 595 function jsonToggle(label, data) { 596 var wrap = el('div', { margin: '4px 0' }); 597 var btn = el('span', { 598 cursor: 'pointer', color: '#89b4fa', textDecoration: 'underline', fontSize: '11px' 599 }, label); 600 var pre = el('pre', { 601 display: 'none', background: '#11111b', color: '#a6adc8', padding: '8px', 602 borderRadius: '4px', overflow: 'auto', maxHeight: '200px', margin: '4px 0 0', 603 fontSize: '11px', whiteSpace: 'pre-wrap', wordBreak: 'break-all' 604 }); 605 try { 606 pre.textContent = JSON.stringify(data, null, 2); 607 } catch (e) { 608 pre.textContent = '(unable to serialize)'; 609 } 610 btn.addEventListener('click', function () { 611 pre.style.display = pre.style.display === 'none' ? 'block' : 'none'; 612 }); 613 wrap.appendChild(btn); 614 wrap.appendChild(pre); 615 return wrap; 616 } 617 618 function highlightSlots() { 619 debugStore.forEach(function (entry) { 620 var elem = document.getElementById(entry.elementId); 621 if (!elem) return; 622 elem.style.outline = '2px dashed ' + (entry.status === 'rendered' ? '#89b4fa' : '#f38ba8'); 623 elem.style.outlineOffset = '2px'; 624 elem.classList.add(DEBUG_OUTLINE_CLASS); 625 }); 626 } 627 628 function removeHighlights() { 629 var elems = document.querySelectorAll('.' + DEBUG_OUTLINE_CLASS); 630 elems.forEach(function (elem) { 631 elem.style.outline = ''; 632 elem.style.outlineOffset = ''; 633 elem.classList.remove(DEBUG_OUTLINE_CLASS); 634 }); 635 } 636 637 function renderDebugPanel() { 638 var panel = el('div'); 639 panel.id = PANEL_ID; 640 applyStyles(panel, panelStyles); 641 642 buildHeader(panel, function () { destroyDebugPanel(); }); 643 buildSummary(panel); 644 buildSlotList(panel); 645 646 document.body.appendChild(panel); 647 highlightSlots(); 648 } 649 650 function destroyDebugPanel() { 651 var existing = document.getElementById(PANEL_ID); 652 if (existing) existing.parentNode.removeChild(existing); 653 removeHighlights(); 654 } 655 656 window.kevelDebug = function () { 657 var existing = document.getElementById(PANEL_ID); 658 if (existing) { 659 destroyDebugPanel(); 660 } else { 661 renderDebugPanel(); 662 } 663 }; 664 665 window.kevelDebug.log = function () { 666 var rows = []; 667 debugStore.forEach(function (e) { 668 if (e.decisions.length === 0) { 669 rows.push({ 670 element: e.elementId,
671 status: e.status, 672 decision: '-', 673 flightId: '-', 674 creativeId: '-', 675 adId: '-', 676 campaignId: '-', 677 type: '-', 678 breakpoint: e.breakpoint 679 }); 680 } else { 681 e.decisions.forEach(function (d, i) { 682 rows.push({ 683 element: e.elementId, 684 status: e.status, 685 decision: (i + 1) + '/' + e.decisions.length, 686 flightId: d.flightId || '-', 687 creativeId: d.creativeId || '-', 688 adId: d.adId || '-', 689 campaignId: d.campaignId || '-', 690 type: d.contents && d.contents[0] ? d.contents[0].type : '-', 691 breakpoint: e.breakpoint 692 }); 693 }); 694 } 695 }); 696 console.table(rows); 697 }; 698 699 // -- Init -- 700 function init() { 701 if (isBot()) return; 702 703 var userKey = initUserKey(); 704 initSegments(userKey); 705 706 var elements = document.querySelectorAll('[data-kevel-zone-ids]'); 707 elements.forEach(function (el) { 708 processElement(el); 709 }); 710 } 711 712 init(); 713 714})();
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.