PageSourceSearch

https://tecidoskite.com.br/wp-content/themes/tecidoskite/assets/js…?ver=e7e10faf67b54c017dd06f033c6fbca0

js tecidoskite.com.br collected 2026-10-05 03:41:39 UTC 4,086 bytes, 140 lines download raw bytes

1/**
2 * youtube-embed.js — utilidades compartilhadas dos embeds de YouTube.
3 *
4 * Consumido por video-block.js, que só cria o iframe no clique do play (lazy-load).
5 */
6(function (w) {
7  /**
8   * Garante enablejsapi=1 (e origin) na URL do embed.
9   * Sem enablejsapi o player nao expõe a IFrame API e o GTM nao consegue
10   * rastrear play/pause/progresso/conclusao do video.
11   */
12  function withJsApi(src) {
13    const sep = src.indexOf('?') === -1 ? '?' : '&';
14    let url = src;
15
16    if (!/[?&]enablejsapi=/.test(url)) {
17      url += sep + 'enablejsapi=1';
18    }
19
20    if (!/[?&]origin=/.test(url) && w.location.origin) {
21      url += '&origin=' + encodeURIComponent(w.location.origin);
22    }
23
24    return url;
25  }
26
27  let iframeApiPromise = null;
28
29  function loadYouTubeIframeApi() {
30    if (iframeApiPromise) return iframeApiPromise;
31
32    iframeApiPromise = new Promise(function (resolve) {
33      if (w.YT && w.YT.Player) {
34        resolve(w.YT);
35        return;
36      }
37
38      const previousReady = w.onYouTubeIframeAPIReady;
39      w.onYouTubeIframeAPIReady = function () {
40        if (typeof previousReady === 'function') previousReady();
41        resolve(w.YT);
42      };
43
44      const tag = document.createElement('script');
45      tag.src = 'https://www.youtube.com/iframe_api';
46      document.head.appendChild(tag);
47    });
48
49    return iframeApiPromise;
50  }
51
52  /**
53   * Empurra play/pause/progresso/conclusao para o dataLayer.
54   *
55   * O gatilho nativo de video do GTM so reconhece youtube.com; o embed usa
56   * youtube-nocookie.com (para nao gravar cookie antes do consentimento), entao
57   * os eventos precisam ser enviados na mao mesmo com enablejsapi=1.
58   */
59  function trackVideo(iframe, videoLabel) {
60    w.dataLayer = w.dataLayer || [];
61
62    const PROGRESS_MARKS = [25, 50, 75, 90];
63    let sentMarks = [];
64    let progressTimer = null;
65    let started = false;
66    let completed = false;
67
68    function pushEvent(eventName, extra) {
69      w.dataLayer.push(Object.assign({
70        event: eventName,
71        video_title: videoLabel
72      }, extra || {}));
73    }
74
75    function stopProgressPolling() {
76      if (progressTimer) {
77        clearInterval(progressTimer);
78        progressTimer = null;
79      }
80    }
81
82    function checkProgress(player) {
83      const duration = player.getDuration();
84      if (!duration) return;
85
86      const percent = (player.getCurrentTime() / duration) * 100;
87      PROGRESS_MARKS.forEach(function (mark) {
88        if (percent >= mark && sentMarks.indexOf(mark) === -1) {
89          sentMarks.push(mark);
90          pushEvent('video_progress', {
91            video_percent: mark,
92            video_current_time: Math.round(player.getCurrentTime()),
93            video_duration: Math.round(duration)
94          });
95        }
96      });
97    }
98
99    loadYouTubeIframeApi().then(function (YT) {
100      new YT.Player(iframe, {
101        events: {
102          onStateChange: function (e) {
103            const player = e.target;
104
105            if (e.data === YT.PlayerState.PLAYING) {
106              if (!started) {
107                started = true;
108                pushEvent('video_start');
109              }
110              stopProgressPolling();
111              progressTimer = setInterval(function () { checkProgress(player); }, 1000);
112            }
113
114            if (e.data === YT.PlayerState.PAUSED) {
115              stopProgressPolling();
116              pushEvent('video_pause', {
117                video_current_time: Math.round(player.getCurrentTime()),
118                video_duration: Math.round(player.getDuration())
119              });
120            }
121
122            if (e.data === YT.PlayerState.ENDED) {
123              stopProgressPolling();
124              if (!completed) {
125                completed = true;
126                pushEvent('video_complete', {
127                  video_duration: Math.round(player.getDuration())
128                });
129              }
130            }
131          }
132        }
133      });
134    });
135  }
136
137  w.tecidoskiteYouTube = w.tecidoskiteYouTube || {};
138  w.tecidoskiteYouTube.withJsApi = withJsApi;
139  w.tecidoskiteYouTube.trackVideo = trackVideo;
140})(window);

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.