1/** 2 * GA4 impression ·×¬ 3 * - ÂоÝ: data-ga-impression °ÀÉÕ¤Í×ÁÇ 4 * - ȯ²Ð¾ò·ï: Í×ÁǤ¬²èÌÌÆâ¤Ë 50% °Ê¾åɽ¼¨¤µ¤ì¤¿¥¿¥¤¥ß¥ó¥° 5 * - ¥Ñ¥é¥á¡¼¥¿: ¼«¿È¤Þ¤¿¤ÏÁÄÀè¤Î onclick ¤«¤é gtag Âè3°ú¿ô¤ò¼èÆÀ 6 * - Á÷¿®: gtag('event', 'impression', onclick Æâ¥Ñ¥é¥á¡¼¥¿¤ÈƱ°ì) 7 * - À©¸Â: 1Í×ÁǤˤĤƱ°ì¥Ú¡¼¥¸Æâ¤Ç 1²ó¤Î¤ß 8 * - Glide Åù¥«¥ë¡¼¥»¥ë: ɽ¼¨Ã楹¥é¥¤¥É¡Ê.glide__slide--active¡Ë¤Î¤ß·×¬ 9 */ 10(function() { 11 'use strict'; 12 13 var IMPRESSION_SENT = 'gaImpressionSent'; 14 var THRESHOLD = 0.5; 15 var GTAG_MAX_RETRY = 50; 16 var OBSERVE_DEBOUNCE_MS = 100; 17 18 var observer = null; 19 var gtagRetry = 0; 20 var observeTimer = null; 21 22 var GTAG_HANDLER_ATTRS = ['onclick', 'onchange']; 23 24 /** 25 * onclick ʸ»úÎ󤫤é gtag('event', 'xxx', {...}) ¤ÎÂè3°ú¿ô¤ò²òÀÏ 26 * event ̾¤Ï click / ad_click / change Åù¤¹¤Ù¤ÆÂÐ¾Ý 27 * @param {string} onclickStr onclick °ÀÃÍ 28 * @returns {Object|null} 29 */ 30 function parseGtagParams(onclickStr) { 31 if (!onclickStr) return null; 32 33 var match = onclickStr.match( 34 /gtag\s*\(\s*['"]event['"]\s*,\s*['"][^'"]+['"]\s*,\s*(\{[\s\S]*?\})\s*\)/ 35 ); 36 if (!match) return null; 37 38 try { 39 return (new Function('return (' + match[1] + ')'))(); 40 } catch (e) { 41 console.error('[ga-impression] onclick ²òÀÏ¥¨¥é¡¼:', e, onclickStr); 42 return null; 43 } 44 } 45 46 /** 47 * ·×¬Í×ÁǼ«¿È¤«¤é¿ÆÊý¸þ¤Ø onclick ¤òõº÷¤·¡¢gtag ¥Ñ¥é¥á¡¼¥¿¤ò¼èÆÀ 48 * ²èÁü¥Ð¥Ê¡¼Åù: img ¤Ë data-ga-impression¡¢gtag ¤ÏÁÄÀè a Åù¤Ë¤¢¤ë¾ì¹ç¤ËÂбþ 49 * @param {Element} el ·×¬ÂоÝÍ×ÁÇ 50 * @returns {Object|null} 51 */ 52 function getGtagParamsFromNode(node) { 53 for (var i = 0; i < GTAG_HANDLER_ATTRS.length; i++) { 54 var params = parseGtagParams(node.getAttribute(GTAG_HANDLER_ATTRS[i])); 55 if (params) return params; 56 } 57 return null; 58 } 59 function getGtagParams(el) { 60 // ¼«¿È ¢ª ÁÄÀè 61 var node = el; 62 while (node && node !== document.documentElement) { 63 var params = getGtagParamsFromNode(node); 64 if (params) return params; 65 node = node.parentElement; 66 } 67 // »Ò¹¡Êcheckbox ºß»Ò input ¾åŪ¾ì¹ç¡Ë 68 if (el.querySelectorAll) { 69 var children = el.querySelectorAll(GTAG_HANDLER_ATTRS.map(function(a) { 70 return '[' + a + '*="gtag"]'; 71 }).join(',')); 72 for (var j = 0; j < children.length; j++) { 73 var childParams = getGtagParamsFromNode(children[j]); 74 if (childParams) return childParams; 75 } 76 } 77 return null; 78 } 79 80 /** 81 * Glide ¥«¥ë¡¼¥»¥ëÆâ¤Ïɽ¼¨Ã楹¥é¥¤¥É¤Î¤ßµö²Ä 82 * ¡Êtrack ¤Î overflow:unset Åù¤ÇÎÙÀÜ¥¹¥é¥¤¥É¤¬ IO ¤Ë¾è¤ë¤Î¤òËɤ°¡Ë 83 * @param {Element} el 84 * @returns {boolean} 85 */ 86 function isCarouselSlideEligible(el) { 87 var slide = el.closest ? el.closest('.glide__slide') : null; 88 if (!slide) return true; 89 90 if (slide.classList.contains('glide__slide--clone')) return false; 91 92 var root = slide.closest('.glide') || 93 (slide.closest('.glide__track') && slide.closest('.glide__track').parentElement); 94 if (!root) return true; 95 96 var active = root.querySelector('.glide__slide--active'); 97 if (active) { 98 return slide.classList.contains('glide__slide--active'); 99 } 100 101 // mount Á°: ÀèÆ¬¥¹¥é¥¤¥É¤Î¤ß 102 var first = root.querySelector('.glide__slide:not(.glide__slide--clone)'); 103 return !first || slide === first; 104 } 105 106 /** 107 * ¥Ó¥å¡¼¥Ý¡¼¥È¤ËÂФ¹¤ë²Ä»ëÌÌÀÑÈæ¤¬ threshold °Ê¾å¤« 108 * ¡Ê¥¹¥é¥¤¥ÉÀÚÂØ¸å¤Ë IO ¤¬ºÆÈ¯²Ð¤·¤Ê¤¤¾ì¹ç¤Î¥Õ¥©¡¼¥ë¥Ð¥Ã¥¯¡Ë 109 * @param {Element} el 110 * @returns {boolean} 111 */ 112 function isVisibleEnough(el) { 113 var rect = el.getBoundingClientRect(); 114 if (rect.width <= 0 || rect.height <= 0) return false; 115 116 var vh = window.innerHeight || document.documentElement.clientHeight; 117 var vw = window.innerWidth || document.documentElement.clientWidth; 118 var visibleH = Math.min(rect.bottom, vh) - Math.max(rect.top, 0); 119 var visibleW = Math.min(rect.right, vw) - Math.max(rect.left, 0); 120 if (visibleH <= 0 || visibleW <= 0) return false; 121 122 return (visibleH * visibleW) / (rect.width * rect.height) >= THRESHOLD; 123 } 124 125 /** 126 * impression ¥¤¥Ù¥ó¥È¤òÁ÷¿®¡ÊƱ°ìÍ×ÁǤÏ1²ó¤Î¤ß¡Ë 127 * @param {Element} el ·×¬ÂоÝÍ×ÁÇ 128 */ 129 function sendImpression(el) { 130 if (el.dataset[IMPRESSION_SENT]) return; 131 if (!isCarouselSlideEligible(el)) return; 132 133 var params = getGtagParams(el); 134 if (!params) return; 135 136 if (typeof gtag !== 'function') return; 137 138 gtag('event', 'impression', params); 139 el.dataset[IMPRESSION_SENT] = '1'; 140 observer.unobserve(el); 141 } 142 143 /**
144 * ²Ä»ë¤Ê¤éÁ÷¿®¤ò»î¹Ô¡ÊGlide ¥¹¥é¥¤¥ÉÀÚÂØ»þÍÑ¡Ë 145 * @param {Element} el 146 */ 147 function trySendIfVisible(el) { 148 if (!el || el.dataset[IMPRESSION_SENT]) return; 149 if (!isCarouselSlideEligible(el)) return; 150 if (!isVisibleEnough(el)) return; 151 sendImpression(el); 152 } 153 154 /** 155 * ¥¢¥¯¥Æ¥£¥Ö¤Ë¤Ê¤Ã¤¿ Glide ¥¹¥é¥¤¥ÉÆâ¤Î·×¬Âоݤò½èÍý 156 * @param {Element} slide 157 */ 158 function onGlideSlideActivated(slide) { 159 if (!slide || !slide.querySelectorAll) return; 160 var targets = slide.querySelectorAll('[data-ga-impression]'); 161 for (var i = 0; i < targets.length; i++) { 162 registerElement(targets[i]); 163 trySendIfVisible(targets[i]); 164 } 165 } 166 167 /** 168 * ·×¬ÂоÝÍ×ÁǤò Observer ¤ËÅÐÏ¿ 169 * lazy ²èÁü¤Ï load ¸å¤ËÅÐÏ¿¡Ê¹â¤µ 0 Âкö¡Ë 170 * @param {Element} el 171 */ 172 function registerElement(el) { 173 if (!el || el.dataset[IMPRESSION_SENT]) return; 174 if (!el.hasAttribute('data-ga-impression')) return; 175 176 if (el.tagName === 'IMG' && !el.complete) { 177 el.addEventListener('load', function onLoad() { 178 el.removeEventListener('load', onLoad); 179 if (!el.dataset[IMPRESSION_SENT]) { 180 observer.observe(el); 181 trySendIfVisible(el); 182 } 183 }); 184 return; 185 } 186 187 observer.observe(el); 188 } 189 190 /** 191 * ·×¬ÂоÝÍ×ÁǤò°ì³çÅÐÏ¿ 192 * @param {Document|Element} root õº÷µ¯ÅÀ¡Ê¾Êά»þ¤Ï document Á´ÂÎ¡Ë 193 */ 194 function observe(root) { 195 var scope = root || document; 196 scope.querySelectorAll('[data-ga-impression]').forEach(registerElement); 197 } 198 199 /** 200 * MutationObserver ÍÑ debounce ÅÐÏ¿ 201 * @param {Document|Element} root 202 */ 203 function scheduleObserve(root) { 204 clearTimeout(observeTimer); 205 observeTimer = setTimeout(function() { 206 observe(root); 207 }, OBSERVE_DEBOUNCE_MS); 208 } 209 210 /** ½é´ü²½½èÍý */ 211 function init() { 212 observer = new IntersectionObserver(function(entries) { 213 entries.forEach(function(entry) { 214 // isIntersecting ¤Ï 1px ¤Ç¤â true¡£50% °Ê¾å¤Î¤È¤¤Î¤ß 215 if (entry.isIntersecting && entry.intersectionRatio >= THRESHOLD) { 216 sendImpression(entry.target); 217 } 218 }); 219 }, { 220 threshold: THRESHOLD 221 }); 222 223 observe(document); 224 225 new MutationObserver(function(mutations) { 226 mutations.forEach(function(m) { 227 if (m.type === 'attributes' && m.attributeName === 'class') { 228 var t = m.target; 229 if (t.classList && 230 t.classList.contains('glide__slide') && 231 t.classList.contains('glide__slide--active') && 232 !t.classList.contains('glide__slide--clone')) { 233 onGlideSlideActivated(t); 234 } 235 return; 236 } 237 238 m.addedNodes.forEach(function(node) { 239 if (node.nodeType !== 1) return; 240 if (node.hasAttribute('data-ga-impression')) { 241 registerElement(node); 242 } 243 if (node.querySelectorAll) { 244 scheduleObserve(node); 245 } 246 }); 247 }); 248 }).observe(document.body, { 249 childList: true, 250 subtree: true, 251 attributes: true, 252 attributeFilter: ['class'] 253 }); 254 } 255 256 /** gtag ÆÉ¤ß¹þ¤ßÂÔ¤Á¡ÊºÇÂçÌó5ÉÃ¡Ë */ 257 function waitAndInit() { 258 if (typeof gtag === 'function' && document.body) { 259 init(); 260 } else if (gtagRetry++ < GTAG_MAX_RETRY) { 261 setTimeout(waitAndInit, 100); 262 } 263 } 264 265 if (document.readyState === 'loading') { 266 document.addEventListener('DOMContentLoaded', waitAndInit); 267 } else { 268 waitAndInit(); 269 } 270 271 /** 272 * ưŪÄɲ峥󥯥ó¥ÄÍÑ¡ÊAJAX¡¦¥Ú¡¼¥¸¥ó¥°¸å¤Ë¸Æ¤Ó½Ð¤·¡Ë 273 * »ÈÍÑÎã: window.gaImpression.observe(document.getElementById('listContainer')); 274 */ 275 window.gaImpression = { 276 observe: observe 277 }; 278 279})();
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.