top of page

Schedule your service

Keine idee was mit deinem Velo los ist? Wir kommen und helfen sofort bei dir.

Check out our availability and book the date and time that works for you

WE LOVE... bike, bike, bike :)

Subscribe Form

Thanks for submitting!

©2023 by VELOV.ch - Proudly created by Velolove

bottom of page
// ===================================================================== // VELOV — Performance Patch v1.0 // Install: Wix Editor → Settings → Custom Code → + Add Custom Code // Place code in: BODY END // Apply to: All pages // ===================================================================== // What this does: // 1. Adds loading="lazy" to every img below the fold (CWV improvement) // 2. Adds decoding="async" to all images (parallel decode) // 3. Promotes hero image (first img with class .hero or first viewport img) // to fetchpriority="high" for faster LCP // 4. Adds rel="noopener noreferrer" to external links missing it (security) // 5. Auto-adds aria-label to icon-only buttons (a11y + SEO) // ===================================================================== (function () { 'use strict'; // Wait for DOM (Wix renders progressively) var ready = function (fn) { if (document.readyState !== 'loading') fn(); else document.addEventListener('DOMContentLoaded', fn); }; ready(function () { // ----- 1. LAZY-LOAD IMAGES BELOW FOLD ----- var foldHeight = window.innerHeight || 800; var imgs = document.querySelectorAll('img'); var firstImage = null; imgs.forEach(function (img, idx) { // Skip if already has loading attribute if (!img.hasAttribute('loading')) { var rect = img.getBoundingClientRect(); var isAboveFold = rect.top < foldHeight && rect.top >= -50; img.setAttribute('loading', isAboveFold ? 'eager' : 'lazy'); } // Decoding async on everything if (!img.hasAttribute('decoding')) { img.setAttribute('decoding', 'async'); } // Track first image for fetchpriority if (idx === 0 && !firstImage) firstImage = img; }); // ----- 2. HERO IMAGE = FETCHPRIORITY HIGH ----- var hero = document.querySelector('img.hero, [class*="hero"] img, .Hero img, header img') || firstImage; if (hero && !hero.hasAttribute('fetchpriority')) { hero.setAttribute('fetchpriority', 'high'); hero.setAttribute('loading', 'eager'); } // ----- 3. EXTERNAL LINKS: noopener ----- var anchors = document.querySelectorAll('a[target="_blank"]'); anchors.forEach(function (a) { var rel = a.getAttribute('rel') || ''; if (!/noopener/.test(rel) || !/noreferrer/.test(rel)) { a.setAttribute('rel', (rel + ' noopener noreferrer').trim()); } }); // ----- 4. ICON-ONLY BUTTONS GET ARIA-LABEL ----- var buttons = document.querySelectorAll('button, a[role="button"]'); buttons.forEach(function (btn) { var text = (btn.textContent || '').trim(); var hasLabel = btn.hasAttribute('aria-label') || btn.hasAttribute('aria-labelledby'); if (!text && !hasLabel) { var titleAttr = btn.getAttribute('title'); if (titleAttr) { btn.setAttribute('aria-label', titleAttr); } } }); // ----- 5. PRECONNECT TO WHATSAPP (warm connection) ----- var hasWaPreconnect = document.querySelector('link[rel="preconnect"][href*="wa.me"]'); if (!hasWaPreconnect) { var link = document.createElement('link'); link.rel = 'preconnect'; link.href = 'https://wa.me'; document.head.appendChild(link); } // ----- 6. GA4 EVENT TRACKING (fires only if gtag present) ----- function trackEvent(eventName, params) { if (typeof window.gtag === 'function') { window.gtag('event', eventName, params || {}); } } // WhatsApp clicks document.addEventListener('click', function (e) { var target = e.target.closest('a[href*="wa.me"], a[href*="whatsapp"]'); if (target) { trackEvent('whatsapp_click', { link_url: target.href, link_text: target.textContent.trim().slice(0, 100) }); } }); // Phone clicks document.addEventListener('click', function (e) { var target = e.target.closest('a[href^="tel:"]'); if (target) { trackEvent('phone_click', { link_url: target.href }); } }); // Pannendienst CTAs document.addEventListener('click', function (e) { var target = e.target.closest( 'a[href*="pannendienst"], a[href*="notfall"], button[data-cta="pannendienst"]' ); if (target) { trackEvent('pannendienst_cta', { source: window.location.pathname }); } }); // Booking form submit document.addEventListener('submit', function (e) { var form = e.target; if (form.matches('form[data-booking], form[id*="book"], form[class*="booking"]')) { trackEvent('booking_form_submit', { form_id: form.id || 'unknown' }); } }); // 75% scroll on homepage if (window.location.pathname === '/' || window.location.pathname === '') { var fired = false; window.addEventListener( 'scroll', function () { if (fired) return; var scrollDepth = (window.scrollY + window.innerHeight) / document.documentElement.scrollHeight; if (scrollDepth >= 0.75) { fired = true; trackEvent('scroll_75_homepage'); } }, { passive: true } ); } console.log('[VELOV] Performance + tracking patch loaded'); }); })();