PageSourceSearch

https://www.goo-net.com/common_v2/js/ga_impression.js?20260630

js goo-net.com collected 2026-10-01 10:30:52 UTC 8,127 bytes, 279 lines download raw bytes

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.