1/** 2 * GA4 é¦é¡µè§é¢ CTR åç¹ 3 * äºä»¶: home_content_view/click (å¸¸è§æ¿å), home_promo_view/click (æ¨è使¿å) 4 * èå´: div.index-content ul.video-items div.video-item 5 * æ¨è使 è¯: ul.video-items.home_promo 6 */ 7(function () { 8 'use strict'; 9 10 if (typeof gtag !== 'function') return; 11 12 var userType = window.__home_user_type__ || 'new'; 13 var viewedSet = new Set(); 14 var SELECTOR = 'div.index-content ul.video-items div.video-item'; 15 16 /** 17 * ä» video-item å ç´ æåäºä»¶åæ° 18 * @param {Element} el - div.video-item å ç´ 19 * @returns {Object|null} 20 */ 21 function extractMeta(el) { 22 var vid = el.dataset.vid; 23 if (!vid) return null; 24 25 var ul = el.closest('ul.video-items'); 26 if (!ul) return null; 27 28 // module_name: ul çä¸ä¸ä¸ªå å¼ div ä¸ç h2 ææ¬ 29 var moduleName = ''; 30 var prev = ul.previousElementSibling; 31 if (prev) { 32 var h2 = prev.querySelector('h2'); 33 if (h2) moduleName = h2.textContent.trim(); 34 } 35 36 // position: li å¨ ul ä¸çä½ç½®ï¼ä»1å¼å§ï¼ 37 var li = el.closest('li'); 38 var position = 0; 39 if (li && ul) { 40 var children = ul.children; 41 for (var i = 0; i < children.length; i++) { 42 if (children[i].tagName === 'LI') { 43 position++; 44 if (children[i] === li) break; 45 } 46 } 47 } 48 49 return { 50 content_id: String(vid), 51 module_name: moduleName, 52 position: position, 53 page_name: 'homepage', 54 user_type: userType, 55 is_promo: ul.classList.contains('home_promo') 56 }; 57 } 58 59 /** 60 * æ ¹æ®å æ°æ®åéå¯¹åº GA4 äºä»¶ 61 * @param {string} action - 'view' æ 'click' 62 * @param {Object} meta - extractMeta è¿åç对象 63 */ 64 function sendEvent(action, meta) { 65 var prefix = meta.is_promo ? 'home_promo_' : 'home_content_'; 66 var params = { 67 content_id: meta.content_id, 68 module_name: meta.module_name, 69 position: meta.position, 70 page_name: meta.page_name, 71 user_type: meta.user_type 72 }; 73 gtag('event', prefix + action, params); 74 } 75 76 /** 77 * åå§åæå åç¹å»è¿½è¸ª 78 */ 79 function init() { 80 var items = document.querySelectorAll(SELECTOR); 81 if (!items.length) return; 82 83 // æå çå¬ 84 if (typeof IntersectionObserver === 'function') { 85 var observer = new IntersectionObserver(function (entries) { 86 for (var i = 0; i < entries.length; i++) { 87 var entry = entries[i]; 88 if (!entry.isIntersecting) continue; 89 90 var meta = extractMeta(entry.target); 91 if (!meta) continue; 92 93 var key = meta.content_id + '_' + meta.module_name + '_' + meta.position; 94 if (viewedSet.has(key)) continue; 95 96 viewedSet.add(key); 97 sendEvent('view', meta); 98 observer.unobserve(entry.target); 99 } 100 }, { threshold: 0.5 }); 101 102 for (var i = 0; i < items.length; i++) { 103 observer.observe(items[i]); 104 } 105 } 106 107 // ç¹å»çå¬ - äºä»¶å§æ 108 var container = document.querySelector('div.index-content'); 109 if (container) { 110 container.addEventListener('click', function (e) { 111 var videoItem = e.target.closest('div.video-item[data-vid]'); 112 if (!videoItem) return; 113 // ç¡®è®¤å¨ video-items å表å 114 if (!videoItem.closest('ul.video-items')) return; 115 116 var meta = extractMeta(videoItem); 117 if (meta) { 118 sendEvent('click', meta); 119 } 120 }); 121 } 122 } 123 124 // DOM 就绪ååå§å 125 if (document.readyState === 'loading') { 126 document.addEventListener('DOMContentLoaded', init); 127 } else { 128 init(); 129 } 130})();
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.