templates/base.html.twig line 1

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.     <!-- Google Tag Manager -->
  5.     <script>(function (w, d, s, l, i) {
  6.             w[l] = w[l] || [];
  7.             w[l].push({
  8.                 'gtm.start':
  9.                     new Date().getTime(), event: 'gtm.js'
  10.             });
  11.             var f = d.getElementsByTagName(s)[0],
  12.                 j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
  13.             j.async = true;
  14.             j.src =
  15.                 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
  16.             f.parentNode.insertBefore(j, f);
  17.         })(window, document, 'script', 'dataLayer', 'GTM-NJJFCJ');</script>
  18.     <!-- End Google Tag Manager -->
  19.     <!-- Meta Pixel Code -->
  20.     <script>
  21.         !function (f, b, e, v, n, t, s) {
  22.             if (f.fbq) return;
  23.             n = f.fbq = function () {
  24.                 n.callMethod ?
  25.                     n.callMethod.apply(n, arguments) : n.queue.push(arguments)
  26.             };
  27.             if (!f._fbq) f._fbq = n;
  28.             n.push = n;
  29.             n.loaded = !0;
  30.             n.version = '2.0';
  31.             n.queue = [];
  32.             t = b.createElement(e);
  33.             t.async = !0;
  34.             t.src = v;
  35.             s = b.getElementsByTagName(e)[0];
  36.             s.parentNode.insertBefore(t, s)
  37.         }(window, document, 'script',
  38.             'https://connect.facebook.net/en_US/fbevents.js');
  39.         fbq('init', '1233084501283271');
  40.         fbq('track', 'PageView');
  41.     </script>
  42.     <noscript><img height="1" width="1" style="display:none"
  43.                    src="https://www.facebook.com/tr?id=1233084501283271&ev=PageView&noscript=1"
  44.         /></noscript>
  45.     <!-- End Meta Pixel Code -->
  46.     <meta charset="UTF-8">
  47.     <link rel="stylesheet" href="https://use.typekit.net/qir3knc.css">
  48.     <title>{% block title %} {% endblock %}</title>
  49.     {% block meta_description %}
  50.         <meta name="description" content="{% block desc %}{% endblock %}">
  51.     {% endblock %}
  52.     {% block canonical %}<link rel="canonical" href="{{ app.request.uri }}">{% endblock %}
  53.     <link rel="icon" type="image/png" href="{{ asset('img/favicon/favicon-96x96.png') }}" sizes="96x96"/>
  54.     <link rel="icon" type="image/svg+xml" href="{{ asset('img/favicon/favicon.svg') }}"/>
  55.     <link rel="shortcut icon" href="{{ asset('img/favicon/favicon.ico') }}"/>
  56.     <link rel="apple-touch-icon" sizes="180x180" href="{{ asset('img/favicon/apple-touch-icon.png') }}"/>
  57.     <meta name="apple-mobile-web-app-title" content="Autanet.cz"/>
  58.     <link rel="manifest" href="{{ asset('img/favicon/site.webmanifest') }}"/>
  59.     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  60.     {# Run `composer require symfony/webpack-encore-bundle` to start using Symfony UX #}
  61.     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"
  62.             integrity="sha512-3gJwYpMe3QewGELv8k/BX9vcqhryRdzRMxVfq6ngyWXwo03GFEzjsUm8Q7RZcHPHksttq7/GFoxjCVUjkjvPdw=="
  63.             crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  64.     <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet">
  65.     <link href="{{ asset('plugins/OverlayScrollbars-1.x/css/OverlayScrollbars.min.css') }}" rel="stylesheet">
  66.     <link href="{{ asset('plugins/Gallery-master/css/blueimp-gallery.min.css') }}" rel="stylesheet">
  67.     <link href="{{ asset('plugins/slick/slick.css') }}" rel="stylesheet">
  68.     <link href="{{ asset('fonts/style.css') }}" rel="stylesheet">
  69.     {% block stylesheets %}
  70.         {{ encore_entry_link_tags('app') }}
  71.     {% endblock %}
  72.     {% block javascripts %}
  73.         {{ encore_entry_script_tags('app') }}
  74.     {% endblock %}
  75.     {# Autanet Analytics – globální anonymní identita pro raw analytics a Partner atribuci #}
  76.     <script>
  77.         window.AutanetAnalytics = (() => {
  78.             const VISITOR_COOKIE = 'autanet_analytics_visitor';
  79.             const SESSION_STORAGE_KEY = 'autanet_analytics_session';
  80.             const SESSION_TIMEOUT_MS = 30 * 60 * 1000;
  81.             const CMP_RETRY_INTERVAL_MS = 100;
  82.             const CMP_RETRY_LIMIT_MS = 30 * 1000;
  83.             const pageviewKey = createKey();
  84.             const pendingIdentityCallbacks = [];
  85.             let consentKnown = false;
  86.             let consentGranted = false;
  87.             let cmpListenerAttached = false;
  88.             let cmpStartedAt = Date.now();
  89.             initConsent();
  90.             function createKey() {
  91.                 if (window.crypto && typeof window.crypto.randomUUID === 'function') {
  92.                     return window.crypto.randomUUID();
  93.                 }
  94.                 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, character => {
  95.                     const random = Math.random() * 16 | 0;
  96.                     const value = character === 'x' ? random : (random & 0x3 | 0x8);
  97.                     return value.toString(16);
  98.                 });
  99.             }
  100.             function getCookie(name) {
  101.                 const prefix = name + '=';
  102.                 const cookies = document.cookie ? document.cookie.split('; ') : [];
  103.                 for (const cookie of cookies) {
  104.                     if (cookie.startsWith(prefix)) {
  105.                         return decodeURIComponent(cookie.substring(prefix.length));
  106.                     }
  107.                 }
  108.                 return null;
  109.             }
  110.             function setVisitorCookie(value) {
  111.                 document.cookie = VISITOR_COOKIE
  112.                     + '=' + encodeURIComponent(value)
  113.                     + '; Path=/; Max-Age=31536000; SameSite=Lax; Secure';
  114.             }
  115.             function deleteVisitorCookie() {
  116.                 document.cookie = VISITOR_COOKIE
  117.                     + '=; Path=/; Max-Age=0; SameSite=Lax; Secure';
  118.             }
  119.             function clearIdentity() {
  120.                 deleteVisitorCookie();
  121.                 try {
  122.                     localStorage.removeItem(SESSION_STORAGE_KEY);
  123.                 } catch (error) {
  124.                     // Pokud localStorage není dostupný, není třeba dělat nic dalšího.
  125.                 }
  126.             }
  127.             function getIdentity() {
  128.                 if (!consentKnown || !consentGranted) {
  129.                     return null;
  130.                 }
  131.                 let visitorKey = getCookie(VISITOR_COOKIE);
  132.                 if (!visitorKey) {
  133.                     visitorKey = createKey();
  134.                     setVisitorCookie(visitorKey);
  135.                 }
  136.                 const now = Date.now();
  137.                 let sessionData = null;
  138.                 try {
  139.                     sessionData = JSON.parse(localStorage.getItem(SESSION_STORAGE_KEY));
  140.                 } catch (error) {
  141.                     sessionData = null;
  142.                 }
  143.                 if (
  144.                     !sessionData
  145.                     || typeof sessionData.key !== 'string'
  146.                     || typeof sessionData.lastActivity !== 'number'
  147.                     || now - sessionData.lastActivity > SESSION_TIMEOUT_MS
  148.                 ) {
  149.                     sessionData = {
  150.                         key: createKey(),
  151.                         lastActivity: now
  152.                     };
  153.                 } else {
  154.                     sessionData.lastActivity = now;
  155.                 }
  156.                 try {
  157.                     localStorage.setItem(
  158.                         SESSION_STORAGE_KEY,
  159.                         JSON.stringify(sessionData)
  160.                     );
  161.                 } catch (error) {
  162.                     sessionData = null;
  163.                 }
  164.                 return {
  165.                     visitorKey: visitorKey,
  166.                     sessionKey: sessionData ? sessionData.key : null,
  167.                     pageviewKey: pageviewKey
  168.                 };
  169.             }
  170.             function flushPendingIdentityCallbacks() {
  171.                 if (!consentKnown) {
  172.                     return;
  173.                 }
  174.                 const identity = consentGranted ? getIdentity() : null;
  175.                 while (pendingIdentityCallbacks.length > 0) {
  176.                     const callback = pendingIdentityCallbacks.shift();
  177.                     callback(identity);
  178.                 }
  179.             }
  180.             function withIdentity(callback, timeoutMs = 5000) {
  181.                 if (consentKnown) {
  182.                     callback(consentGranted ? getIdentity() : null);
  183.                     return;
  184.                 }
  185.                 let completed = false;
  186.                 const wrappedCallback = identity => {
  187.                     if (completed) {
  188.                         return;
  189.                     }
  190.                     completed = true;
  191.                     callback(identity);
  192.                 };
  193.                 pendingIdentityCallbacks.push(wrappedCallback);
  194.                 setTimeout(() => {
  195.                     wrappedCallback(null);
  196.                 }, timeoutMs);
  197.             }
  198.             function applyConsent(tcData) {
  199.                 const consents = tcData.purpose && tcData.purpose.consents
  200.                     ? tcData.purpose.consents
  201.                     : {};
  202.                 consentKnown = true;
  203.                 consentGranted = (
  204.                     tcData.gdprApplies === false
  205.                     || (
  206.                         consents[1] === true
  207.                         && consents[8] === true
  208.                         && consents[9] === true
  209.                     )
  210.                 );
  211.                 if (!consentGranted) {
  212.                     clearIdentity();
  213.                 }
  214.                 flushPendingIdentityCallbacks();
  215.             }
  216.             function attachCmpListener() {
  217.                 if (cmpListenerAttached) {
  218.                     return;
  219.                 }
  220.                 if (typeof window.__tcfapi !== 'function') {
  221.                     if (Date.now() - cmpStartedAt < CMP_RETRY_LIMIT_MS) {
  222.                         setTimeout(attachCmpListener, CMP_RETRY_INTERVAL_MS);
  223.                     }
  224.                     return;
  225.                 }
  226.                 cmpListenerAttached = true;
  227.                 window.__tcfapi('addEventListener', 2, (tcData, success) => {
  228.                     if (!success || !tcData) {
  229.                         return;
  230.                     }
  231.                     if (
  232.                         tcData.eventStatus !== 'tcloaded'
  233.                         && tcData.eventStatus !== 'useractioncomplete'
  234.                     ) {
  235.                         return;
  236.                     }
  237.                     applyConsent(tcData);
  238.                 });
  239.             }
  240.             function initConsent() {
  241.                 cmpStartedAt = Date.now();
  242.                 attachCmpListener();
  243.             }
  244.             function getState() {
  245.                 return {
  246.                     consentKnown: consentKnown,
  247.                     consentGranted: consentGranted,
  248.                     pageviewKey: pageviewKey,
  249.                     visitorKey: consentGranted ? getCookie(VISITOR_COOKIE) : null,
  250.                     session: consentGranted
  251.                         ? localStorage.getItem(SESSION_STORAGE_KEY)
  252.                         : null
  253.                 };
  254.             }
  255.             return {
  256.                 getIdentity: getIdentity,
  257.                 withIdentity: withIdentity,
  258.                 clearIdentity: clearIdentity,
  259.                 getState: getState
  260.             };
  261.         })();
  262.     </script>
  263.     <script language="JavaScript" type="text/javascript">
  264.         document.write('<img src=https://toplist.cz/dot.asp?id=61738&amp;http=' + escape(document.referrer) + '&amp;wi=' + escape(window.screen.width) + '&amp;he=' + escape(window.screen.height) + '&amp;t=' + escape(document.title) + ' width="1" height="1" border=0 alt=" " />');
  265.     </script>
  266.     <noscript><img src=https://toplist.cz/dot.asp?id=61738 border="0" alt=" " width="1" height="1"/></noscript>
  267.     <!-- (C)2000-2015 Gemius SA - gemiusAudience / autanet.cz / Homepage -->
  268.     <script type="text/javascript">
  269.         var pp_gemius_identifier = 'ogg70HNn3AMZzJdBUqRQipcPzStg1JrY61PGru.QL2P.47';
  270.         var pp_gemius_use_cmp = true;
  271.         function gemius_pending(i) {
  272.             window[i] = window[i] || function () {
  273.                 var x = window[i + '_pdata'] = window[i + '_pdata'] || [];
  274.                 x[x.length] = arguments;
  275.             };
  276.         };
  277.         gemius_pending('gemius_hit');
  278.         gemius_pending('gemius_event');
  279.         gemius_pending('pp_gemius_hit');
  280.         gemius_pending('pp_gemius_event');
  281.         (function (d, t) {
  282.             try {
  283.                 var gt = d.createElement(t), s = d.getElementsByTagName(t)[0],
  284.                     l = 'http' + ((location.protocol == 'https:') ? 's' : '');
  285.                 gt.setAttribute('async', 'async');
  286.                 gt.setAttribute('defer', 'defer');
  287.                 gt.src = l + '://spir.hit.gemius.pl/xgemius.js';
  288.                 s.parentNode.insertBefore(gt, s);
  289.             } catch (e) {
  290.             }
  291.         })(document, 'script');
  292.     </script>
  293.     {% set queryParams = app.request.query.all %}
  294.     {% if isBasicDealer is defined and isBasicDealer %}
  295.         <meta name="robots" content="noindex, follow">
  296.     {% elseif queryParams['vehicleId'] is defined or app.environment != 'prod' %}
  297.         <meta name="robots" content="noindex, nofollow">
  298.     {% else %}
  299.         <meta name="robots" content="all">
  300.     {% endif %}
  301.     {% block mobileBranding %}
  302.         {% set excludedRoutes = [
  303.             'app_homepage',
  304.             'page_vehicle_search',
  305.             'page_vehicle_detail',
  306.             'page_vehicle_detail_seo',
  307.             'page_dealer',
  308.             'page_dealer_detail',
  309.             'page_dealer_vehicle',
  310.             'page_prohlidka_ojeteho_auta',
  311.             'vehicle_inspection_form',
  312.             'vehicle_search_form',
  313.             'dealer_inspection_form',
  314.             'page_proverit_auto'
  315.         ] %}
  316.         {% set currentRoute = app.request.attributes.get('_route') %}
  317.         {% if currentRoute not in excludedRoutes %}
  318.             <script async src="https://cdn.performax.cz/yi/adsbypx/px_autoads.js?aab=ulite"></script>
  319.             <link rel="stylesheet" href="https://cdn.performax.cz/yi/adsbypx/px_autoads.css"/>
  320.         {% endif %}
  321.     {% endblock %}
  322. </head>
  323. <body class="{% block body_class %}{% endblock %}">
  324. <!-- Google Tag Manager (noscript) -->
  325. <noscript>
  326.     <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJJFCJ"
  327.             height="0" width="0" style="display:none;visibility:hidden"></iframe>
  328. </noscript>
  329. <!-- End Google Tag Manager (noscript) -->
  330. </body>
  331. <header class="header">
  332.     <div class="header__overlay js-header__overlay"></div>
  333.     <div class="header__container">
  334.         <a class="header__logo" href="{{ path('app_homepage') }}">
  335.             <img src="{{ asset('img/header__logo.svg') }}" alt="" loading="lazy">
  336.         </a>
  337.         <div class="header__collapse js-header__collapse">
  338.             <nav class="header__nav">
  339.                 <div class="header__nav-dropdown">
  340.                     <div class="header__nav-dropdown-toggler js-header__nav-dropdown-toggler">Nabídka vozidel</div>
  341.                     <div class="header__nav-dropdown-collapse">
  342.                         <div class="header__nav-submenu">
  343.                             <a class="header__nav-submenu-item" href="/osobni-vozidla">Osobní</a>
  344.                             <a class="header__nav-submenu-item" href="/uzitkova-vozidla">Užitková</a>
  345.                             <a class="header__nav-submenu-item" href="/nakladni-vozidla">Nákladní</a>
  346.                             <a class="header__nav-submenu-item" href="/obytna-vozidla">Obytná</a>
  347.                             <a class="header__nav-submenu-item" href="/motorky-skutry">Motorky</a>
  348.                             <a class="header__nav-submenu-item" href="/privesy-a-navesy">Přívěsy a návěsy</a>
  349.                             <a class="header__nav-submenu-item" href="/autobusy">Autobusy</a>
  350.                             <a class="header__nav-submenu-item" href="/pracovni-stroje">Pracovní stroje</a>
  351.                             <a class="header__nav-submenu-item" href="/nahradni-dily">Náhradní díly</a>
  352.                             <a class="header__nav-submenu-item" href="/prislusenstvi">Příslušenství</a>
  353.                         </div>
  354.                     </div>
  355.                 </div>
  356.                 <a href="{{ path('page_dealer') }}">Prodejci</a>
  357.                 <a href="{{ path('page_blog', { urlKind: 'testy-aut'  }) }}">Testy aut</a>
  358.                 <a href="{{ path('page_proverit_auto') }}">Prověřit auto</a>
  359.                 <div class="header__nav-dropdown">
  360.                     <div class="header__nav-dropdown-toggler js-header__nav-dropdown-toggler">Magazín</div>
  361.                     <div class="header__nav-dropdown-collapse">
  362.                         <div class="header__nav-submenu">
  363.                             <a class="header__nav-submenu-item" href="{{ path('page_blog', { urlKind: 'novinky'  }) }}">Novinky</a>
  364.                             <a class="header__nav-submenu-item"
  365.                                href="{{ path('page_blog', { urlKind: 'rady-a-tipy'  }) }}">Rady a tipy</a>
  366.                             <a class="header__nav-submenu-item"
  367.                                href="{{ path('page_blog', { urlKind: 'nove-modely'  }) }}">Nové modely</a>
  368.                             <a class="header__nav-submenu-item" href="{{ path('page_blog', { urlKind: 'ojetiny'  }) }}">Ojetiny</a>
  369.                             <a class="header__nav-submenu-item"
  370.                                href="{{ path('page_blog', { urlKind: 'auto-a-zivot'  }) }}"> Auto a život</a>
  371.                         </div>
  372.                     </div>
  373.                 </div>
  374.             </nav>
  375.         </div>
  376.         <div class="header__toggler js-header__toggler">
  377.             <span></span>
  378.         </div>
  379.     </div>
  380. </header>
  381. {% include 'admin-menu.html.twig' %}
  382. <main{% block main_class %}{% endblock %}>
  383.     {% if show_flash_messages is not defined or show_flash_messages %}
  384.         {% for label, messages in app.flashes %}
  385.             {% for message in messages %}
  386.                 <div class="alert alert-{{ label }}">
  387.                     {{ message }}
  388.                 </div>
  389.             {% endfor %}
  390.         {% endfor %}
  391.     {% endif %}
  392.     {% block body %}  {% endblock %}
  393.     <script>
  394.         const bannerBasePath = '/img/partner/banner';
  395.         const bannerRoutes = {
  396.             desktop: '{{ path('app_banner') }}',
  397.             mobile: '{{ path('app_mobile_banner') }}'
  398.         };
  399.         const currentPath = window.location.pathname;
  400.         Promise.all([
  401.             fetch(bannerRoutes.desktop).then(response => response.json()),
  402.             fetch(bannerRoutes.mobile).then(response => response.json())
  403.         ])
  404.             .then(([desktopBannerData, mobileBannerData]) => {
  405.                 const bannerContainer = document.getElementById('banner-container');
  406.                 let mobileBannerContainer = document.getElementById('banner-mobile-container');
  407.                 const blogTextContainer = document.getElementById('blog-text');
  408.                 if (blogTextContainer) {
  409.                     if (mobileBannerContainer) {
  410.                         mobileBannerContainer.dataset.autanetPartnerBannerPlacement = 'B08';
  411.                     }
  412.                     const allParagraphs = Array.from(blogTextContainer.querySelectorAll('p')).filter(p => !p.querySelector('img'));
  413.                     const fifthParagraph = allParagraphs[4];
  414.                     if (fifthParagraph) {
  415.                         if (!mobileBannerContainer) {
  416.                             mobileBannerContainer = document.createElement('div');
  417.                             mobileBannerContainer.id = 'banner-mobile-container';
  418.                             mobileBannerContainer.classList.add('banner-mobile');
  419.                             mobileBannerContainer.dataset.autanetPartnerBannerPlacement = 'B08';
  420.                             document.body.appendChild(mobileBannerContainer);
  421.                         }
  422.                         mobileBannerContainer.innerHTML = `
  423.                 <a href="${mobileBannerData.url}">
  424.                     <img src="${bannerBasePath}/${mobileBannerData.image}" alt="Partner banner">
  425.                 </a>
  426.             `;
  427.                         fifthParagraph.insertAdjacentElement('afterend', mobileBannerContainer);
  428.                     }
  429.                 }
  430.                 if (bannerContainer && desktopBannerData) {
  431.                     bannerContainer.innerHTML = `
  432.             <a href="${desktopBannerData.url}" data-banner-id="${desktopBannerData.id}" data-autanet-partner-id="${desktopBannerData.autanet_partner_id}" class="banner-link">
  433.                 <img src="${bannerBasePath}/${desktopBannerData.image}" alt="Partner banner">
  434.             </a>
  435.         `;
  436.                 }
  437.                 if (mobileBannerContainer && mobileBannerData) {
  438.                     mobileBannerContainer.innerHTML = `
  439.             <a href="${mobileBannerData.url}" data-banner-id="${mobileBannerData.id}" data-autanet-partner-id="${mobileBannerData.autanet_partner_id}" class="banner-link">
  440.                 <img src="${bannerBasePath}/${mobileBannerData.image}" alt="Partner banner">
  441.             </a>
  442.         `;
  443.                 }
  444.                 const trackAutanetPartnerBannerImpression = (link, container) => {
  445.                     if (!container) {
  446.                         return;
  447.                     }
  448.                     const placement = container.dataset.autanetPartnerBannerPlacement;
  449.                     if (!['B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08'].includes(placement)) {
  450.                         return;
  451.                     }
  452.                     const bannerId = link.getAttribute('data-banner-id');
  453.                     const partnerId = link.getAttribute('data-autanet-partner-id');
  454.                     if (!bannerId || !partnerId || !window.AutanetAnalytics) {
  455.                         return;
  456.                     }
  457.                     let visibleSince = null;
  458.                     let impressionSent = false;
  459.                     const observer = new IntersectionObserver(entries => {
  460.                         entries.forEach(entry => {
  461.                             if (impressionSent) {
  462.                                 return;
  463.                             }
  464.                             if (entry.isIntersecting && entry.intersectionRatio >= 0.5) {
  465.                                 if (visibleSince === null) {
  466.                                     visibleSince = Date.now();
  467.                                 }
  468.                                 if (Date.now() - visibleSince >= 1000) {
  469.                                     impressionSent = true;
  470.                                     observer.disconnect();
  471.                                     window.AutanetAnalytics.withIdentity(identity => {
  472.                                         if (!identity) {
  473.                                             return;
  474.                                         }
  475.                                         const body = new URLSearchParams({
  476.                                             event_type: 'banner_impression',
  477.                                             placement: placement,
  478.                                             banner_id: bannerId,
  479.                                             partner_id: partnerId,
  480.                                             device: window.matchMedia('(max-width: 767px)').matches ? 'mobile' : 'desktop',
  481.                                             visitor_key: identity.visitorKey,
  482.                                             session_key: identity.sessionKey,
  483.                                             pageview_key: identity.pageviewKey
  484.                                         });
  485.                                         fetch('/analytics/event', {
  486.                                             method: 'POST',
  487.                                             headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
  488.                                             body: body.toString(),
  489.                                             keepalive: true
  490.                                         });
  491.                                     });
  492.                                 }
  493.                             } else {
  494.                                 visibleSince = null;
  495.                             }
  496.                         });
  497.                     }, {threshold: [0, 0.5, 1]});
  498.                     observer.observe(link);
  499.                     const timer = window.setInterval(() => {
  500.                         if (impressionSent || !document.body.contains(link)) {
  501.                             window.clearInterval(timer);
  502.                             return;
  503.                         }
  504.                         const rect = link.getBoundingClientRect();
  505.                         const visibleHeight = Math.max(0, Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0));
  506.                         const ratio = rect.height > 0 ? visibleHeight / rect.height : 0;
  507.                         if (ratio >= 0.5) {
  508.                             if (visibleSince === null) {
  509.                                 visibleSince = Date.now();
  510.                             }
  511.                             if (Date.now() - visibleSince >= 1000) {
  512.                                 impressionSent = true;
  513.                                 window.clearInterval(timer);
  514.                                 observer.disconnect();
  515.                                 window.AutanetAnalytics.withIdentity(identity => {
  516.                                     if (!identity) {
  517.                                         return;
  518.                                     }
  519.                                     const body = new URLSearchParams({
  520.                                         event_type: 'banner_impression',
  521.                                         placement: placement,
  522.                                         banner_id: bannerId,
  523.                                         partner_id: partnerId,
  524.                                         device: window.matchMedia('(max-width: 767px)').matches ? 'mobile' : 'desktop',
  525.                                         visitor_key: identity.visitorKey,
  526.                                         session_key: identity.sessionKey,
  527.                                         pageview_key: identity.pageviewKey
  528.                                     });
  529.                                     fetch('/analytics/event', {
  530.                                         method: 'POST',
  531.                                         headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
  532.                                         body: body.toString(),
  533.                                         keepalive: true
  534.                                     });
  535.                                 });
  536.                             }
  537.                         } else {
  538.                             visibleSince = null;
  539.                         }
  540.                     }, 250);
  541.                 };
  542.                 document.querySelectorAll('.banner-link').forEach(link => {
  543.                     const container = link.closest('#banner-container, #banner-mobile-container');
  544.                     trackAutanetPartnerBannerImpression(link, container);
  545.                     link.addEventListener('click', function (e) {
  546.                         e.preventDefault();
  547.                         const bannerId = this.getAttribute('data-banner-id');
  548.                         const partnerId = this.getAttribute('data-autanet-partner-id');
  549.                         const container = this.closest('#banner-container, #banner-mobile-container');
  550.                         const placement = container ? container.dataset.autanetPartnerBannerPlacement : null;
  551.                         if (
  552.                             ['B01', 'B02', 'B03', 'B04', 'B05', 'B06', 'B07', 'B08'].includes(placement)
  553.                             && partnerId
  554.                             && window.AutanetAnalytics
  555.                         ) {
  556.                             window.AutanetAnalytics.withIdentity(identity => {
  557.                                 if (identity) {
  558.                                     const body = new URLSearchParams({
  559.                                         event_type: 'banner_click',
  560.                                         placement: placement,
  561.                                         banner_id: bannerId,
  562.                                         partner_id: partnerId,
  563.                                         device: window.matchMedia('(max-width: 767px)').matches ? 'mobile' : 'desktop',
  564.                                         visitor_key: identity.visitorKey,
  565.                                         session_key: identity.sessionKey,
  566.                                         pageview_key: identity.pageviewKey
  567.                                     });
  568.                                     fetch('/analytics/event', {
  569.                                         method: 'POST',
  570.                                         headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
  571.                                         body: body.toString(),
  572.                                         keepalive: true
  573.                                     });
  574.                                 }
  575.                             });
  576.                         }
  577.                         fetch(`/banner/${bannerId}/click`, {method: 'POST'})
  578.                             .then(() => {
  579.                                 window.location.href = this.href;
  580.                             });
  581.                     });
  582.                 });
  583.             })
  584.             .catch(error => console.error('Error loading banners:', error));
  585.     </script>
  586. </main>
  587. {% block footer %}
  588.     {{ render(controller( 'App\\Controller\\PageController::footer', { request: app.request } )) }}
  589. {% endblock %}
  590. <script src="{{ asset('plugins/OverlayScrollbars-1.x/js/jquery.overlayScrollbars.min.js') }}"></script>
  591. <script src="{{ asset('plugins/Gallery-master/js/blueimp-gallery.min.js') }}"></script>
  592. <script src="{{ asset('plugins/slick/slick.min.js') }}"></script>
  593. <script src="{{ asset('js/default.js') }}?v=2026082401"></script>
  594. </html>