templates/base.html.twig line 35

  1. <!DOCTYPE html>
  2. <html xmlns="https://www.w3.org/1999/xhtml" xmlns:fb="http://ogp.me/ns/fb#" prefix="og: http://ogp.me/ns#" lang="{{ app.request.getLocale() }}">
  3.     {% set busters = getBustersValues() %}
  4.     {% set webpEnabled = isWebpEnabled() %}
  5.     {% set iubendaCookie = getIubendaCookie(app.request.locale) %}
  6.     <head>
  7.         {% apply spaceless %}
  8.             <meta charset="utf-8">
  9.             <meta name="viewport" content="width=device-width, initial-scale=1">
  10.             <meta http-equiv="X-UA-Compatible" content="IE=edge">
  11.             {% block meta_group %}
  12.                 {% if metatags is defined and metatags %}
  13.                     {% include 'partials/metatags/_custom.html.twig' %}
  14.                 {% else %}
  15.                     {% include 'partials/metatags/_default.html.twig' %}
  16.                 {% endif %}
  17.             {% endblock %}
  18.             {% block meta_canonical %}
  19.                 {% if app.request.attributes.get('_route') %}
  20.                     <link rel="canonical" href="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|default({}))|lower }}" />
  21.                 {% endif %}
  22.             {% endblock %}
  23.             {% block meta_alternate %}
  24.                 {% if hreflangs is defined and hreflangs %}
  25.                     {% for hreflang in hreflangs %}
  26.                         <link rel="alternate" hreflang="{{ hreflang.locale }}" href="{{ hreflang.href|lower }}" />
  27.                     {% endfor %}
  28.                 {% else %}
  29.                     {% for locale in locales %}
  30.                         <link rel="alternate" hreflang="{{ locale }}" href="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|default({})|merge({'_locale': locale}))|lower }}" />
  31.                     {% endfor %}
  32.                 {% endif %}
  33.             {% endblock %}
  34.             {% block meta_robots %}
  35.                 {% if app.environment == 'dev' or app.environment == 'test' %}
  36.                     <meta name="robots" content="noindex,nofollow">
  37.                     <meta name="googlebot" content="noindex,nofollow">
  38.                 {% else %}
  39.                     <meta name="robots" content="index,follow">
  40.                     <meta name="googlebot" content="index,follow">
  41.                 {% endif %}
  42.             {% endblock %}
  43.             <link rel="icon" href="{{ asset('assets/images/frontend/favicon.ico') }}" sizes="any">
  44.             {% set icons = [32, 76, 120, 152, 167, 180, 192, 196]%}
  45.             {% for icon in icons %}
  46.                 <link rel="apple-touch-icon" sizes="{{ icon }}x{{ icon }}" href="{{ asset('assets/images/frontend/webpage-icons/icon-' ~ icon ~ 'x' ~ icon ~ '.png') }}">
  47.             {% endfor %}
  48.             <meta name="apple-mobile-web-app-title" content="Kioene">
  49.             <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  50.             <meta name="apple-mobile-web-app-capable" content="yes">
  51.             <meta name="theme-color" content="#166938">
  52.             <meta name="msapplication-navbutton-color" content="#166938">
  53.             <meta name="geo.region" content="IT">
  54.             <meta name="geo.placename" content="Villanova di Camposampiero">
  55.             <meta name="geo.position" content="45.491379;11.96371">
  56.             <meta name="ICBM" content="45.491379, 11.96371">
  57.             <meta name="msapplication-config" content="none">
  58.             {% block stylesheets %}
  59.                 {# <link rel="preconnect" href="https://fonts.googleapis.com">
  60.                 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  61.                 <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap" rel="stylesheet"> #}
  62.                 <link rel="preconnect" href="https://fonts.googleapis.com">
  63.                 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  64.                 <link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap" rel="stylesheet">
  65.                 <link rel="stylesheet" href="https://use.typekit.net/uil7luu.css">
  66.                 <!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
  67.                 {# <link rel="preload" as="image" href="{{ asset('assets/images/frontend/bg-land-large-mobile.png') }}" type="image/png"> #}
  68.                 <link rel="preload" as="image" href="{{ asset('assets/images/webp/frontend/bg-land-large-mobile.webp') }}" type="image/webp">
  69.                 <link rel="preload" href="{{ asset('assets/fonts/market-fresh/market-fresh-bold.woff2') }}" as="font" type="font/woff2" crossorigin>
  70.                 <link rel="preload" fetchpriority="high" href="{{ asset('assets/css/frontend/fonts.css') }}?v={{ busters['css/frontend/fonts.css'] is defined ? busters['css/frontend/fonts.css'] }}" as="style">
  71.                 <link rel="stylesheet" href="{{ asset('assets/css/frontend/fonts.css') }}?v={{ busters['css/frontend/fonts.css'] is defined ? busters['css/frontend/fonts.css'] }}">
  72.                 <link rel="preload" href="{{ asset('assets/css/frontend/pofo.css') }}?v={{ busters['css/frontend/pofo.css'] is defined ? busters['css/frontend/pofo.css'] }}" as="style">
  73.                 <link rel="stylesheet" href="{{ asset('assets/css/frontend/pofo.css') }}?v={{ busters['css/frontend/pofo.css'] is defined ? busters['css/frontend/pofo.css'] }}">
  74.                 <link rel="preload" href="{{ asset('assets/css/frontend/main.css') }}?v={{ busters['css/frontend/main.css'] is defined ? busters['css/frontend/main.css'] }}" as="style">
  75.                 <link rel="stylesheet" href="{{ asset('assets/css/frontend/main.css') }}?v={{ busters['css/frontend/main.css'] is defined ? busters['css/frontend/main.css'] }}">
  76.             {% endblock %}
  77.             <script type="application/ld+json">
  78.                 {
  79.                     "@context": "https://schema.org",
  80.                     "@type": "Organization",
  81.                     "url": "https://www.kioene.com",
  82.                     "logo": "{{ asset('assets/svg/logo-kioene.svg') }}"
  83.                 }
  84.             </script>
  85.             {% block javascripts '' %}
  86.         {% endapply %}
  87.         <script type="text/javascript">
  88.             var pixel_PageView__now = Math.floor(Date.now() / 1000);
  89.             var pixel_PageView__eventID = pixel_PageView__now + '_' + Math.random().toString(36).substr(2, 9);
  90.             var pixel_em = '';
  91.             var pixel_ph = '';
  92.         </script>
  93.         {% block iubenda_config %}
  94.         <script type="text/javascript">
  95.             var iubendaIds = [];
  96.             var locale = '{{ app.request.locale }}';
  97.             iubendaIds[locale] = {
  98.                 'siteId' : '{{ iubenda[app.request.locale].siteId }}',
  99.                 'cookiePolicyId' : '{{ iubenda[app.request.locale].cookiePolicyId }}',
  100.                 'locale': '{{ iubenda[app.request.locale].locale }}'
  101.             };
  102.         </script>
  103.         {% endblock %}
  104.         <script>
  105.             var url__tracking_pixel="/api/tracking-pixel-api-conversion/ajax.php";
  106.             var url__tracking_pinterest="/api/tracking-pinterest-api-conversion/ajax.php";
  107.             var tracking__locale = '{{ app.request.locale }}';
  108.             var tracking__viewcontent__title = '';
  109.             var tracking__viewcontent__ids = [];
  110.             var tracking__viewcontent__type = 'page';
  111.         </script>
  112.         <!-- Google Tag Manager -->
  113.         <script type="text/javascript">
  114.             window.dataLayer = window.dataLayer || [];
  115.             function gtag(){dataLayer.push(arguments);}
  116.         </script>
  117.         <script type="text/javascript">dataLayer.push({locale: '{{ app.request.locale }}'});</script>
  118.         <script type="application/javascript">
  119.             var checkPixelCallback = false;
  120.             var consent_analytics_storage = 'denied';
  121.             var consent_ad_storage = 'denied';
  122.             var consent_personalization_storage = 'denied';
  123.             var consent_functionality_storage = 'denied';
  124.             var consent_security_storage = 'denied';
  125.             var iubendaCookie = null;
  126.             var cookieName = '_iub_cs-'+iubendaIds[locale]['cookiePolicyId'] + "=";
  127.             var ca = document.cookie.split(';');
  128.             for(var i=0; i<ca.length; i++) {
  129.                 var c = ca[i];
  130.                 while (c.charAt(0)==' ') c = c.substring(1);
  131.                 if (c.indexOf(cookieName) == 0) {
  132.                     iubendaCookie = c.substring(cookieName.length,c.length)
  133.                 }
  134.             }
  135.             if (iubendaCookie) {
  136.                 iubendaCookie = decodeURIComponent(iubendaCookie);
  137.                 iubendaCookie = JSON.parse(iubendaCookie);
  138.                 if (iubendaCookie.purposes[5]) {
  139.                     consent_ad_storage = 'granted';
  140.                     var checkPixelCallback = true;
  141.                     dataLayer.push({
  142.                         consense_marketing: true
  143.                     });
  144.                 }
  145.                 if (iubendaCookie.purposes[4]) {
  146.                     consent_analytics_storage = 'granted';
  147.                     dataLayer.push({
  148.                         anonymizeIp: false,
  149.                     });
  150.                 }
  151.                 if (iubendaCookie.purposes[3]) {
  152.                     consent_personalization_storage = 'granted';
  153.                 }
  154.                 if (iubendaCookie.purposes[2]) {
  155.                     consent_functionality_storage = 'granted';
  156.                 }
  157.             } else {
  158.                 dataLayer.push({
  159.                     anonymizeIp: true,
  160.                     consense_marketing: false
  161.                 });
  162.             }
  163.             gtag('consent', 'default', {
  164.                 'ad_storage': consent_ad_storage,
  165.                 'ad_user_data': consent_ad_storage,
  166.                 'ad_personalization': consent_ad_storage,
  167.                 'analytics_storage': consent_analytics_storage,
  168.                 'wait_for_update': 500,
  169.                 // 'personalization_storage': consent_personalization_storage,
  170.                 // 'functionality_storage': consent_functionality_storage,
  171.                 // 'security_storage': consent_security_storage,
  172.             });
  173.         </script>
  174.         {% block gtm_config %}
  175.         <script type="text/javascript">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
  176.                     new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
  177.                 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
  178.                 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
  179.             })(window,document,'script','dataLayer','GTM-MM2BS55');</script>
  180.         {% endblock  %}
  181.         <!-- End Google Tag Manager -->
  182.     </head>
  183.     <body class="body body_{{ app.request.attributes.get('_route')|replace({'_': '-'}) }} {{ app.request.attributes.get('category_slug') ? 'body_' ~ app.request.attributes.get('category_slug') : ''  }} {{ webpEnabled ? 'webp' }} w-100 {% block bodyClass '' %}" {% block bodyStyle '' %}>
  184.     <!-- Google Tag Manager (noscript) -->
  185.     {% block gtm_config_noscript %}
  186.     <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MM2BS55"
  187.                       height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  188.     {% endblock  %}
  189.     <!-- End Google Tag Manager (noscript) -->
  190.         {% block body %}
  191.             <div class="body__layer-transition body__layer-transition_bg-color_jewel" data-js="layer-transition-2"></div>
  192.             <div class="body__layer-transition body__layer-transition_bg-color_la-riojia" data-js="layer-transition-1"></div>
  193.             <div class="body__layer-transition" data-js="layer-loading">
  194.                 <img src="{{ asset('assets/svg/spin-1.1s-100px.svg') }}" alt="loading">
  195.             </div>
  196.             {% block header %}
  197.                 {{ render(controller(
  198.                     'App\\Controller\\DefaultController::headerAction',
  199.                     { 'route': app.request.attributes.get('_route') }
  200.                 )) }}
  201.             {% endblock %}
  202.             <div class="page overflow-hidden">
  203.                 <div class="page__bg"></div>
  204.                 <div class="page__bg-top" data-transition="element-pre-enter"></div>
  205.                 <div class="page__content margin-lr-auto">
  206.                     {% block content '' %}
  207.                 </div>
  208.                 {% block extraContent '' %}
  209.             </div>
  210.             {% block footer %}
  211.                 {% if app.request.locale == 'it' %}
  212.                     {% include 'wheretobuy/_banner.html.twig' with {'padding': true} %}
  213.                 {% else %}
  214.                     <div class="footer-top position-relative z-index-2"></div>
  215.                 {% endif %}
  216.                 {{ render(controller(
  217.                     'App\\Controller\\DefaultController::footerAction', {'banner': true, 'color': 'white', 'currentPath': app.request.get('_route')}
  218.                 )) }}
  219.             {% endblock %}
  220.             {% block modals '' %}
  221.             {% if app.request.locale == 'it' %}
  222.                 <div class="modal micromodal-slide" id="modalVideo" aria-hidden="true">
  223.                   <div class="modal__overlay" tabindex="-1" data-micromodal-close>
  224.                     <div class="modal__container" role="dialog" aria-modal="true" aria-labelledby="modalVideo-title">
  225.                       <header class="modal__header">
  226.                         <button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
  227.                       </header>
  228.                       <main class="modal__content" id="modalVideo-content">
  229.                           <video id="beforeAdterVideo" preload="none" data-heroVideo autoplay muted playsinline>
  230.                               <source src="/assets/video/post-reveal.mov" type="video/mp4; codecs=hvc1">
  231.                               <source src="/assets/video/post-reveal.webm" type="video/webm">
  232.                           </video>
  233.                       </main>
  234.                     </div>
  235.                   </div>
  236.                 </div>
  237.             {% endif %}
  238.         {% endblock %}
  239.         {% block javascripts_body %}
  240.             <script type="text/javascript" src="{{ asset('assets/js/gsap/gsap.js') }}?v={{ busters['js/gsap/gsap.js'] is defined ? busters['js/gsap/gsap.js'] }}"></script>
  241.             <script type="text/javascript" src="{{ asset('assets/js/gsap/ScrollTrigger.js') }}?v={{ busters['js/gsap/ScrollTrigger.js'] is defined ? busters['js/gsap/ScrollTrigger.js'] }}"></script>
  242.             <script type="text/javascript" src="{{ asset('assets/js/frontend/main.js') }}?v={{ busters['js/frontend/main.js'] is defined ? busters['js/frontend/main.js'] }}"></script>
  243.             {% if app.request.locale == 'it' %}
  244.                 <script type="text/javascript">
  245.                     MicroModal.init();
  246.                     // MicroModal.show('modalVideo');
  247.                       document.addEventListener("DOMContentLoaded", function() {
  248.                         // --- CONFIG: imposta una stringa 'YYYY-MM-DD' per testare (o lascia null)
  249.                         const DEBUG_DATE = null; // ex: "2025-10-24" oppure null per usare la data reale
  250.                         // --- helper per formattare la data come YYYY-MM-DD
  251.                         function formatYYYYMMDD(d) {
  252.                           const yyyy = d.getFullYear();
  253.                           const mm = String(d.getMonth() + 1).padStart(2, "0");
  254.                           const dd = String(d.getDate()).padStart(2, "0");
  255.                           return `${yyyy}-${mm}-${dd}`;
  256.                         }
  257.                         // --- ottenere "oggi" rispettando DEBUG_DATE se presente
  258.                         function getTodayDateObject() {
  259.                           if (DEBUG_DATE) {
  260.                             // crea Date da DEBUG_DATE (assume formato YYYY-MM-DD)
  261.                             const parts = DEBUG_DATE.split("-");
  262.                             return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2]));
  263.                           }
  264.                           return new Date();
  265.                         }
  266.                         // --- cookie base helpers ---
  267.                         function setRawCookie(name, value, expiresDate) {
  268.                           const expires = expiresDate ? `; expires=${expiresDate.toUTCString()}` : "";
  269.                           document.cookie = `${name}=${encodeURIComponent(value)}${expires}; path=/`;
  270.                         }
  271.                         function getRawCookie(name) {
  272.                           const value = `; ${document.cookie}`;
  273.                           const parts = value.split(`; ${name}=`);
  274.                           if (parts.length === 2) return decodeURIComponent(parts.pop().split(";").shift());
  275.                           return null;
  276.                         }
  277.                         // --- setta cookie con valore = data odierna (YYYY-MM-DD) e scadenza a mezzanotte successiva ---
  278.                         function setCookieWithDate(name) {
  279.                           const today = getTodayDateObject();
  280.                           const dateStr = formatYYYYMMDD(today);
  281.                           // calcola mezzanotte del giorno successivo
  282.                           const midnight = new Date(today);
  283.                           midnight.setHours(24, 0, 0, 0); // mezzanotte successiva
  284.                           setRawCookie(name, dateStr, midnight);
  285.                           console.log(`[Modal] Imposto cookie "${name}" = ${dateStr} (scade: ${midnight.toString()})`);
  286.                         }
  287.                         // --- ritorna la data memorizzata nel cookie solo se corrisponde alla "data corrente" ---
  288.                         function getValidCookieDate(name) {
  289.                           const stored = getRawCookie(name);
  290.                           if (!stored) return null;
  291.                           const today = getTodayDateObject();
  292.                           const todayStr = formatYYYYMMDD(today);
  293.                           if (stored === todayStr) {
  294.                             console.log(`[Modal] Cookie "${name}" valido per oggi: ${stored}`);
  295.                             return stored;
  296.                           } else {
  297.                             console.log(`[Modal] Cookie "${name}" presente ma non corrisponde a oggi (cookie: ${stored} - oggi: ${todayStr}) -> ignoro`);
  298.                             return null;
  299.                           }
  300.                         }
  301.                         // --- configurazione principale ---
  302.                         const modalId = "modalVideo";
  303.                         const modalCookieName = "modalVideoSeenDate";
  304.                         // se il cookie valido per oggi esiste -> non mostrare la modale
  305.                         if (getValidCookieDate(modalCookieName)) {
  306.                           console.log("[Modal] giĆ  visto oggi: non mostro la modale.");
  307.                           return;
  308.                         }
  309.                         let cookieSet = false;
  310.                         function markModalSeen() {
  311.                           if (cookieSet) return;
  312.                           cookieSet = true;
  313.                           setCookieWithDate(modalCookieName);
  314.                           removeCloseListeners();
  315.                         }
  316.                         // --- listeners fallback per garantire che il cookie venga impostato ---
  317.                         const closeSelectors = `[data-micromodal-close], .micromodal-close`;
  318.                         let closeElements = [];
  319.                         function addCloseListeners() {
  320.                           const modalEl = document.getElementById(modalId);
  321.                           if (!modalEl) {
  322.                             console.warn(`[Modal] elemento con id="${modalId}" non trovato.`);
  323.                             return;
  324.                           }
  325.                           closeElements = Array.from(modalEl.querySelectorAll(closeSelectors));
  326.                           closeElements.forEach(el => el.addEventListener("click", markModalSeen));
  327.                           document.addEventListener("keydown", escHandler);
  328.                           // fallback per event custom se presente
  329.                           document.addEventListener("micromodal-close", markModalSeen);
  330.                         }
  331.                         function removeCloseListeners() {
  332.                           closeElements.forEach(el => {
  333.                             try { el.removeEventListener("click", markModalSeen); } catch(e){}
  334.                           });
  335.                           document.removeEventListener("keydown", escHandler);
  336.                           document.removeEventListener("micromodal-close", markModalSeen);
  337.                         }
  338.                         function escHandler(e) {
  339.                           if (e.key === "Escape" || e.key === "Esc") {
  340.                             const modalEl = document.getElementById(modalId);
  341.                             if (!modalEl) return;
  342.                             const ariaHidden = modalEl.getAttribute("aria-hidden");
  343.                             if (modalEl.classList.contains("is-open") || ariaHidden === "false") {
  344.                               markModalSeen();
  345.                             }
  346.                           }
  347.                         }
  348.                         // --- inizializzazione MicroModal con onClose che imposta il cookie ---
  349.                         MicroModal.init({
  350.                           onClose: () => {
  351.                             console.log("[Modal] MicroModal onClose fired");
  352.                             markModalSeen();
  353.                           }
  354.                         });
  355.                         // aggiungiamo fallback listeners e mostriamo la modale dopo load
  356.                         addCloseListeners();
  357.                         window.addEventListener("load", function() {
  358.                           setTimeout(() => {
  359.                             if (!getValidCookieDate(modalCookieName)) {
  360.                               MicroModal.show(modalId);
  361.                               console.log(`[Modal] Mostro la modale: ${modalId}`);
  362.                             } else {
  363.                               console.log("[Modal] Cookie valido trovato al momento del load: non mostro.");
  364.                             }
  365.                           }, 2000);
  366.                         });
  367.                       });
  368.                 </script>
  369.             {% endif %}
  370.         {% endblock %}
  371.         {% block javascripts_iubenda %}
  372.             <script>
  373.                 var _iub = _iub || [];
  374.                 _iub.csConfiguration = {
  375.                     "invalidateConsentWithoutLog": true,
  376.                     "consentOnContinuedBrowsing": false,
  377.                     "perPurposeConsent": true,
  378.                     "whitelabel": false,
  379.                     "lang": iubendaIds[locale].locale,
  380.                     "siteId": iubendaIds[locale].siteId,
  381.                     "floatingPreferencesButtonDisplay": "bottom-left",
  382.                     "cookiePolicyId": iubendaIds[locale].cookiePolicyId,
  383.                     "callback": {
  384.                         "onPreferenceFirstExpressed": function(event) {
  385.                             onConsent(event);
  386.                         }
  387.                     },
  388.                     "banner": {
  389.                         "closeButtonRejects": true,
  390.                         "rejectButtonDisplay": true,
  391.                         "rejectButtonColor": "#a2c618",
  392.                         "rejectButtonCaptionColor": "white",
  393.                         "explicitWithdrawal": true,
  394.                         "position": "float-center",
  395.                         "textColor": "black",
  396.                         "backgroundColor": "white",
  397.                         "listPurposes": true,
  398.                         "acceptButtonDisplay": true,
  399.                         "acceptButtonColor": "#046A38",
  400.                         "acceptButtonCaptionColor": "white",
  401.                         "customizeButtonDisplay": true,
  402.                         "customizeButtonColor": "#A3A3A3",
  403.                         "customizeButtonCaptionColor": "white"
  404.                     }
  405.                 };
  406.             </script>
  407.             <script type="text/javascript" src="//cdn.iubenda.com/cs/gpp/stub.js"></script>
  408.             <script type="text/javascript" src="//cdn.iubenda.com/cs/iubenda_cs.js" charset="UTF-8" async></script>
  409.         {% endblock %}
  410.     </body>
  411. </html>