PageSourceSearch

https://wordwisebook.com/analytic.js

js wordwisebook.com collected 2026-09-24 14:57:11 UTC 18,924 bytes, 578 lines download raw bytes

1const isPerformanceBot =
2  /Chrome-Lighthouse|PageSpeed|GTmetrix|Googlebot|bingbot|slurp|duckduckbot|baiduspider|yandexbot|bot|crawler|spider|headless|phantom|prerender|selenium|webdriver|lighthouse|pingdom|uptimerobot|semrush|ahrefs|majestic|moz|facebookexternalhit|twitterbot|whatsapp|telegrambot|slackbot|discordbot/i.test(
3    navigator.userAgent
4  ) || navigator.webdriver === true;
5
6const hostname = window.location.hostname;
7const isPageSpeed =
8  hostname.includes("pagespeed") || 
9  hostname.includes("gtmetrix") || 
10  hostname.includes(".netlify.app") || 
11  hostname.includes(".vercel.app") ||
12  hostname.includes("preview") ||
13  /^(localhost|127\.0\.0\.1|0\.0\.0\.0|192\.168\.\d+\.\d+|10\.\d+\.\d+\.\d+)$/.test(hostname);
14
15// Register service worker
16if ("serviceWorker" in navigator) {
17  if (hostname !== "localhost" && hostname !== "127.0.0.1") {
18    window.addEventListener("load", () => {
19      navigator.serviceWorker
20        .register("/sw.js")
21        .then((reg) => {
22          console.log("Service Worker registered.", reg);
23          
24          // Listen for messages from the service worker
25          navigator.serviceWorker.addEventListener('message', (event) => {
26            if (event.data && event.data.type === 'SW_UPDATED') {
27              console.log('Service Worker updated, reloading page...');
28              window.location.reload();
29            }
30          });
31        })
32        .catch((err) =>
33          console.log("Service Worker registration failed:", err)
34        );
35    });
36  } else {
37    console.log("Service Worker not registered on localhost");
38  }
39}
40
41if (
42  // !isPerformanceBot &&
43  // !isPageSpeed &&
44  // hostname !== "localhost" &&
45  // hostname !== "127.0.0.1"
46  true
47) {
48  // Google Analytics (gtag)
49  const gaScript = document.createElement("script");
50  gaScript.src = "https://www.googletagmanager.com/gtag/js?id=G-QBM18BD3WP";
51  gaScript.async = true;
52  document.head.appendChild(gaScript);
53
54  
vendor: 142 bytes, lines 54-59
54window.dataLayer = window.dataLayer || [];
55  function gtag() {
56    dataLayer.push(arguments);
57  }
58  gtag("js", new Date());
59  gtag("config", "
59G-QBM18BD3WP
vendor: 7 bytes, lines 59-61
59");
60
61  
61// Web Vitals
62  // const webVitalsScript = document.createElement("script");
63  // webVitalsScript.src =
64  //   "https://unpkg.com/web-vitals@3/dist/web-vitals.iife.js";
65  // webVitalsScript.async = true;
66  // document.head.appendChild(webVitalsScript);
67
68  // webVitalsScript.onload = () => {
69  //   function sendToGtag({ name, delta, id, value }) {
70  //     gtag("event", name, {
71  //       event_category: "Web Vitals",
72  //       event_label: id,
73  //       value: Math.round(name === "CLS" ? delta * 1000 : value),
74  //       non_interaction: true,
75  //     });
76  //   }
77
78  //   webVitals.getCLS(sendToGtag);
79  //   webVitals.getFID(sendToGtag);
80  //   webVitals.getLCP(sendToGtag);
81  //   webVitals.getFCP(sendToGtag);
82  //   webVitals.getTTFB(sendToGtag);
83  // };
84
85  // Statcounter
86  window.sc_project = 13146153;
87  window.sc_invisible = 1;
88  window.sc_security = "04bec386";
89
90  const scScript = document.createElement("script");
91  scScript.src = "https://www.statcounter.com/counter/counter.js";
92  scScript.async = true;
93  document.head.appendChild(scScript);
94
95  // Helper function to track events
96  window.trackEvent = function(eventName, params = {}) {
97    if (typeof gtag === 'function') {
98      gtag('event', eventName, params);
99    }
100  };
101
102  window.addEventListener("DOMContentLoaded", async () => {
103    // Track page view
104    trackEvent('page_view', {
105      page_path: window.location.pathname,
106      page_title: document.title
107    });
108
109    // GA event tracking
110    const dropZone = document.getElementById("dropZone");
111    if (dropZone) {
112      dropZone.addEventListener("click", function () {
113        trackEvent("drop_zone_click", {
114          event_category: "engagement",
115          event_label: "Drop Zone Clicked"
116        });
117      });
118
119      // Track drag events
120      dropZone.addEventListener("dragover", function () {
121        trackEvent("file_drag_over", {
122          event_category: "engagement",
123          event_label: "File Dragged Over Drop Zone"
124        });
125      }, { once: true });
126    }
127
128    // Track demo button
129    const tryDemoBtn = document.getElementById("tryDemoBtn");
130    if (tryDemoBtn) {
131      tryDemoBtn.addEventListener("click", function () {
132        trackEvent("demo_epub_click", {
133          event_category: "engagement",
134          event_label: "Try Demo EPUB",
135          demo_file: "alice-in-wonderland"
136        });
137      });
138    }
139
140    // Track download button
141    const downloadBtn = document.getElementById("downloadEPUB");
142    if (downloadBtn) {
143      downloadBtn.addEventListener("click", function () {
144        const fileName = window.uploadedFileName || 'unknown';
145        trackEvent("download_epub_click", {
146          event_category: "conversion",
147          event_label: "Download EPUB",
148          file_name: fileName
149        });
150      });
151    }
152
153    // Track Export PDF/XTC button
154    const exportPdfXtcBtns = document.querySelectorAll('[onclick*="openXTCModal"]');
155    exportPdfXtcBtns.forEach(btn => {
156      btn.addEventListener("click", function () {
157        const fileName = window.uploadedFileName || 'unknown';
158        trackEvent("export_pdf_xtc_click", {
159          event_category: "conversion",
160          event_label: "Export PDF/XTC Button Clicked",
161          file_name: fileName
162        });
163      });
164    });
165
166    // Track settings changes
167    const hintLevel = document.getElementById("hintLevel");
168    if (hintLevel) {
169      hintLevel.addEventListener("change", function (e) {
170        trackEvent("hint_level_change", {
171          event_category: "settings",
172          event_label: "Hint Level Changed",
173          value: e.target.value,
174          text: e.target.options[e.target.selectedIndex].text
175        });
176      });
177    }
178
179    const translationLang = document.getElementById("translationLanguage");
180    if (translationLang) {
181      translationLang.addEventListener("change", function (e) {
182        trackEvent("translation_language_change", {
183          event_category: "settings",
184          event_label: "Translation Language Changed",
185          language: e.target.value,
186          language_name: e.target.options[e.target.selectedIndex].text
187        });
188      });
189    }
190
191    const wordwiseStyle = document.getElementById("wordwiseStyle");
192    if (wordwiseStyle) {
193      wordwiseStyle.addEventListener("change", function (e) {
194        trackEvent("wordwise_style_change", {
195          event_category: "settings",
196          event_label: "Display Style Changed",
197          style: e.target.value,
198          style_name: e.target.options[e.target.selectedIndex].text
199        });
200      });
201    }
202
203    const useFullDef = document.getElementById("useFullDefinition");
204    if (useFullDef) {
205      useFullDef.addEventListener("change", (e) => {
206        trackEvent("full_definition_toggle", {
207          event_category: "settings",
208          event_label: "Full Definition Toggle",
209          checked: e.target.checked
210        });
211      });
212    }
213
214    const showPhoneme = document.getElementById("showPhoneme");
215    if (showPhoneme) {
216      showPhoneme.addEventListener("change", (e) => {
217        trackEvent("phoneme_toggle", {
218          event_category: "settings",
219          event_label: "Phoneme Toggle",
220          checked: e.target.checked
221        });
222      });
223    }
224
225    // Track text input
226    const textInput = document.getElementById("textInput");
227    if (textInput) {
228      let inputTimeout;
229      textInput.addEventListener("input", (e) => {
230        clearTimeout(inputTimeout);
231        inputTimeout = setTimeout(() => {
232          const charCount = e.target.value.length;
233          if (charCount > 0) {
234            trackEvent("text_input_used", {
235              event_category: "engagement",
236              event_label: "Text Pasted",
237              character_count: charCount,
238              character_range: charCount < 1000 ? 'short' : charCount < 5000 ? 'medium' : 'long'
239            });
240          }
241        }, 2000);
242      });
243    }
244
245    // Track preview button
246    const previewBtn = document.getElementById("previewBtn");
247    if (previewBtn) {
248      previewBtn.addEventListener("click", function () {
249        trackEvent("preview_text_click", {
250          event_category: "engagement",
251          event_label: "Preview Text Button",
252          mode: "paste_text"
253        });
254      });
255    }
256
257    // Track mode switching
258    const modeUploadEpub = document.getElementById("modeUploadEpub");
259    if (modeUploadEpub) {
260      modeUploadEpub.addEventListener("click", function () {
261        trackEvent("mode_switch", {
262          event_category: "navigation",
263          event_label: "Switch to Upload Mode",
264          mode: "upload"
265        });
266      });
267    }
268
269    const modePasteText = document.getElementById("modePasteText");
270    if (modePasteText) {
271      modePasteText.addEventListener("click", function () {
272        trackEvent("mode_switch", {
273          event_category: "navigation",
274          event_label: "Switch to Paste Mode",
275          mode: "paste"
276        });
277      });
278    }
279
280    // Track extension clicks
281    const extensionImg = document.getElementById("extenstionImg");
282    if (extensionImg) {
283      extensionImg.addEventListener("click", function () {
284        trackEvent("extension_click", {
285          event_category: "engagement",
286          event_label: "Extension Banner Clicked",
287          link_url: "chrome_web_store"
288        });
289      });
290    }
291
292    // Track extension links
293    const extensionLinks = document.querySelectorAll('a[href*="chromewebstore"]');
294    extensionLinks.forEach(link => {
295      link.addEventListener("click", function () {
296        trackEvent("extension_link_click", {
297          event_category: "outbound",
298          event_label: "Chrome Web Store Link",
299          link_url: this.href
300        });
301      });
302    });
303
304    // Track library book clicks
305    const demoBooksGrid = document.getElementById("demoBooksGrid");
306    if (demoBooksGrid) {
307      demoBooksGrid.addEventListener("click", function(e) {
308        const bookCard = e.target.closest('.book-card');
309        if (bookCard) {
310          const title = bookCard.querySelector('.book-title')?.textContent || 'Unknown';
311          const author = bookCard.querySelector('.book-author')?.textContent || 'Unknown';
312          trackEvent("library_book_click", {
313            event_category: "engagement",
314            event_label: "Library Book Selected",
315            book_title: title,
316            book_author: author
317          });
318        }
319      });
320    }
321
322    // Track PWA install
323    const installPwaBtn = document.getElementById('installPwaBtn');
324    if (installPwaBtn) {
325      installPwaBtn.addEventListener("click", function () {
326        trackEvent("pwa_install_click", {
327          event_category: "engagement",
328          event_label: "PWA Install Button Clicked"
329        });
330      });
331    }
332
333    // Track page navigation
334    const prevPage = document.getElementById("prevPage");
335    if (prevPage) {
336      prevPage.addEventListener("click", function () {
337        trackEvent("epub_navigation", {
338          event_category: "engagement",
339          event_label: "Previous Page",
340          direction: "previous"
341        });
342      });
343    }
344
345    const nextPage = document.getElementById("nextPage");
346    if (nextPage) {
347      nextPage.addEventListener("click", function () {
348        trackEvent("epub_navigation", {
349          event_category: "engagement",
350          event_label: "Next Page",
351          direction: "next"
352        });
353      });
354    }
355
356    // Track scroll to top
357    const goToTopBtn = document.getElementById("goToTopBtn");
358    if (goToTopBtn) {
359      goToTopBtn.addEventListener("click", function () {
360        trackEvent("scroll_to_top", {
361          event_category: "navigation",
362          event_label: "Go to Top Button"
363        });
364      });
365    }
366
367    // Track scroll depth
368    let maxScroll = 0;
369    let scrollTimeout;
370    window.addEventListener('scroll', function() {
371      clearTimeout(scrollTimeout);
372      scrollTimeout = setTimeout(() => {
373        const scrollPercent = Math.round((window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100);
374        if (scrollPercent > maxScroll) {
375          maxScroll = scrollPercent;
376          if (scrollPercent >= 25 && scrollPercent < 50) {
377            trackEvent('scroll_depth', { event_category: 'engagement', event_label: '25%', value: 25 });
378          } else if (scrollPercent >= 50 && scrollPercent < 75) {
379            trackEvent('scroll_depth', { event_category: 'engagement', event_label: '50%', value: 50 });
380          } else if (scrollPercent >= 75 && scrollPercent < 90) {
381            trackEvent('scroll_depth', { event_category: 'engagement', event_label: '75%', value: 75 });
382          } else if (scrollPercent >= 90) {
383            trackEvent('scroll_depth', { event_category: 'engagement', event_label: '90%', value: 90 });
384          }
385        }
386      }, 300);
387    });
388
389    // Track slider interaction
390    const sliderHandle = document.querySelector('.slider-handle');
391    if (sliderHandle) {
392      let sliderInteracted = false;
393      sliderHandle.addEventListener('mousedown', function() {
394        if (!sliderInteracted) {
395          trackEvent('slider_interaction', {
396            event_category: 'engagement',
397            event_label: 'Before/After Slider Used',
398            interaction_type: 'mouse'
399          });
400          sliderInteracted = true;
401        }
402      });
403      sliderHandle.addEventListener('touchstart', function() {
404        if (!sliderInteracted) {
405          trackEvent('slider_interaction', {
406            event_category: 'engagement',
407            event_label: 'Before/After Slider Used',
408            interaction_type: 'touch'
409          });
410          sliderInteracted = true;
411        }
412      });
413    }
414
415    // Track time on page
416    let startTime = Date.now();
417    window.addEventListener('beforeunload', function() {
418      const timeSpent = Math.round((Date.now() - startTime) / 1000);
419      trackEvent('time_on_page', {
420        event_category: 'engagement',
421        event_label: 'Time Spent',
422        value: timeSpent,
423        time_range: timeSpent < 30 ? 'short' : timeSpent < 120 ? 'medium' : 'long'
424      });
425    });
426  });
427
428  // Track file upload success/error
429  window.addEventListener('epub_upload_success', function(e) {
430    trackEvent('epub_upload_success', {
431      event_category: 'conversion',
432      event_label: 'EPUB Upload Success',
433      file_name: e.detail?.fileName || 'unknown',
434      file_size: e.detail?.fileSize || 0
435    });
436  });
437
438  window.addEventListener('epub_upload_error', function(e) {
439    trackEvent('epub_upload_error', {
440      event_category: 'error',
441      event_label: 'EPUB Upload Error',
442      error_message: e.detail?.error || 'unknown'
443    });
444  });
445
446  // Track EPUB processing success/error
447  window.addEventListener('epub_process_success', function(e) {
448    trackEvent('epub_process_success', {
449      event_category: 'conversion',
450      event_label: 'EPUB Processing Success',
451      file_name: e.detail?.fileName || 'unknown',
452      language: e.detail?.language || 'unknown',
453      processing_time: e.detail?.processingTime || 0
454    });
455  });
456
457  window.addEventListener('epub_process_error', function(e) {
458    trackEvent('epub_process_error', {
459      event_category: 'error',
460      event_label: 'EPUB Processing Error',
461      error_message: e.detail?.error || 'unknown'
462    });
463  });
464
465  // Track download success
466  window.addEventListener('epub_download_success', function(e) {
467    trackEvent('epub_download_success', {
468      event_category: 'conversion',
469      event_label: 'EPUB Download Success',
470      file_name: e.detail?.fileName || 'unknown',
471      file_size: e.detail?.fileSize || 0
472    });
473  });
474
475  // Track XTC Modal events
476  window.addEventListener('xtc_modal_opened', function(e) {
477    trackEvent('xtc_modal_opened', {
478      event_category: 'conversion',
479      event_label: 'XTC Modal Opened',
480      file_name: e.detail?.fileName || 'unknown'
481    });
482  });
483
484  window.addEventListener('xtc_modal_closed', function(e) {
485    trackEvent('xtc_modal_closed', {
486      event_category: 'conversion',
487      event_label: 'XTC Modal Closed',
488      time_spent: e.detail?.timeSpent || 0
489    });
490  });
491
492  // Track PDF export
493  window.addEventListener('pdf_export_started', function(e) {
494    trackEvent('pdf_export_started', {
495      event_category: 'conversion',
496      event_label: 'PDF Export Started',
497      file_name: e.detail?.fileName || 'unknown'
498    });
499  });
500
501  window.addEventListener('pdf_export_success', function(e) {
502    trackEvent('pdf_export_success', {
503      event_category: 'conversion',
504      event_label: 'PDF Export Success',
505      file_name: e.detail?.fileName || 'unknown',
506      page_count: e.detail?.pageCount || 0,
507      export_time: e.detail?.exportTime || 0
508    });
509  });
510
511  window.addEventListener('pdf_export_error', function(e) {
512    trackEvent('pdf_export_error', {
513      event_category: 'error',
514      event_label: 'PDF Export Error',
515      error_message: e.detail?.error || 'unknown'
516    });
517  });
518
519  // Track XTC export
520  window.addEventListener('xtc_export_started', function(e) {
521    trackEvent('xtc_export_started', {
522      event_category: 'conversion',
523      event_label: 'XTC Export Started',
524      file_name: e.detail?.fileName || 'unknown'
525    });
526  });
527
528  window.addEventListener('xtc_export_success', function(e) {
529    trackEvent('xtc_export_success', {
530      event_category: 'conversion',
531      event_label: 'XTC Export Success',
532      file_name: e.detail?.fileName || 'unknown',
533      file_size: e.detail?.fileSize || 0,
534      export_time: e.detail?.exportTime || 0
535    });
536  });
537
538  window.addEventListener('xtc_export_error', function(e) {
539    trackEvent('xtc_export_error', {
540      event_category: 'error',
541      event_label: 'XTC Export Error',
542      error_message: e.detail?.error || 'unknown'
543    });
544  });
545
546  // Track EPUB to XTC conversion (ruby tag processing)
547  window.addEventListener('epub_xtc_conversion_started', function(e) {
548    trackEvent('epub_xtc_conversion_started', {
549      event_category: 'conversion',
550      event_label: 'EPUB to XTC Conversion Started',
551      file_name: e.detail?.fileName || 'unknown'
552    });
553  });
554
555  window.addEventListener('epub_xtc_conversion_success', function(e) {
556    trackEvent('epub_xtc_conversion_success', {
557      event_category: 'conversion',
558      event_label: 'EPUB to XTC Conversion Success',
559      file_name: e.detail?.fileName || 'unknown',
560      ruby_tags_converted: e.detail?.rubyTagsConverted || 0
561    });
562  });
563
564  // Track PWA install events
565  window.addEventListener('beforeinstallprompt', function(e) {
566    trackEvent('pwa_install_prompt_shown', {
567      event_category: 'pwa',
568      event_label: 'Install Prompt Shown'
569    });
570  });
571
572  window.addEventListener('appinstalled', function() {
573    trackEvent('pwa_installed', {
574      event_category: 'pwa',
575      event_label: 'App Installed Successfully'
576    });
577  });
578}

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.