Error executing template "Designs/Swift/Swift_Page.cshtml"
System.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
 ---> System.ComponentModel.Win32Exception (2): The system cannot find the file specified.
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.Open()
   at Dynamicweb.Data.DatabaseConnectionProvider.CreateConnection(Boolean open)
   at Dynamicweb.Data.Database.CreateConnection()
   at Dynamicweb.Data.Database.CreateDataReader(CommandBuilder commandBuilder, IDbConnection connection, IDbTransaction transaction, Int32 commandTimeout)
   at Dynamicweb.Ecommerce.Products.ProductRepository.GetProductById(String productId, String productVariantId, String productLanguageId)
   at Dynamicweb.Ecommerce.Products.ProductService.FetchMissingProductsInternal(IProductRepository repo, IEnumerable`1 keys)
   at Dynamicweb.Caching.ServiceCache`2.GetCache(IEnumerable`1 keys)
   at Dynamicweb.Ecommerce.Products.ProductService.GetProductById(String productId, String productVariantId, String productLanguageId, User user, Boolean showUntranslated)
   at Dynamicweb.Ecommerce.Frontend.UrlHandling.ProductUrlQueryStringProvider.TryResolveQueryString(NameValueCollection queryString, UrlNode& resolvedPath)
   at Dynamicweb.Frontend.UrlHandling.UrlIndex.GetPathFromQueryString(String queryString)
   at Dynamicweb.Frontend.SearchEngineFriendlyURLs.ResolveQueryString(String fullQueryString, Int32 pageid, String alternatekey)
   at Dynamicweb.Frontend.PageView.ResolveSearchFriendlyUrl()
   at Dynamicweb.Frontend.PageView.get_SearchFriendlyUrl()
   at CompiledRazorTemplates.Dynamic.RazorEngine_75cde2c75af44648826b63b890029277.SetMetaTags()
   at CompiledRazorTemplates.Dynamic.RazorEngine_75cde2c75af44648826b63b890029277.ExecuteAsync()
   at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()
ClientConnectionId:00000000-0000-0000-0000-000000000000
Error Number:2,State:0,Class:20

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 2 @using System 3 @using Dynamicweb 4 @using Dynamicweb.Environment 5 @using Dynamicweb.Frontend 6 7 @functions { 8 string GetCookieOptInPermission(string category) 9 { 10 bool categoryOrAllGranted = false; 11 12 if (CookieManager.IsCookieManagementActive) 13 { 14 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 15 var cookieOptInCategories = CookieManager.GetCookieOptInCategories(); 16 categoryOrAllGranted = cookieOptInCategories.Contains(category) || cookieOptInLevel == CookieOptInLevel.All; 17 } 18 19 return categoryOrAllGranted ? "granted" : "denied"; 20 } 21 22 bool AllowTracking() 23 { 24 bool allowTracking = true; 25 if (CookieManager.IsCookieManagementActive) 26 { 27 var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); 28 var cookieOptInCategories = CookieManager.GetCookieOptInCategories(); 29 30 bool consentEither = (cookieOptInCategories.Contains("Statistical") || cookieOptInCategories.Contains("Marketing")); 31 bool consentFunctional = cookieOptInLevel == CookieOptInLevel.Functional; 32 bool consentAtLeastOne = cookieOptInLevel == CookieOptInLevel.All || (consentFunctional && consentEither); 33 34 allowTracking = consentAtLeastOne; 35 } 36 return allowTracking; 37 } 38 } 39 40 @{ 41 var cartSummaryPageId = Dynamicweb.Content.Services.Pages.GetPageByNavigationTag(Model.Area.ID, "CartSummary")?.ID; 42 bool enableMiniCart = Model.Area.Item?.GetBoolean("EnableOffcanvasMiniCart") ?? false; 43 var offcanvasMiniCartBehaviour = Model.Area.Item?.GetRawValueString("OffcanvasMinicartBehaviour", "3") ?? "3"; 44 bool miniCartEnabled = cartSummaryPageId != null && enableMiniCart; 45 var brandingPageId = Model.Area.Item?.GetInt32("BrandingPage") ?? 0; 46 var themePageId = Model.Area.Item?.GetInt32("ThemesPage") ?? 0; 47 var cssPageId = Model.Area.Item?.GetInt32("CssPage") ?? 0; 48 var brandingPage = brandingPageId != 0 ? Dynamicweb.Content.Services.Pages?.GetPage(brandingPageId) ?? null : null; 49 var themesParagraphs = themePageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(themePageId) ?? null : null; 50 var cssParagraphs = cssPageId != 0 ? Dynamicweb.Content.Services.Paragraphs?.GetParagraphsByPageId(cssPageId) ?? null : null; 51 } 52 53 @if (themesParagraphs != null || brandingPage != null) 54 { 55 string swiftVersion = ReadFile("/Files/Templates/Designs/Swift/swift_version.txt"); 56 bool renderAsResponsive = Model.Area.Item.GetString("DeviceRendering", "responsive").Equals("responsive", StringComparison.OrdinalIgnoreCase); 57 bool renderMobile = Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile || Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet; 58 string responsiveClassDesktop = string.Empty; 59 string responsiveClassMobile = string.Empty; 60 if (renderAsResponsive) 61 { 62 responsiveClassDesktop = " d-none d-xl-block"; 63 responsiveClassMobile = " d-block d-xl-none"; 64 } 65 66 var headerDesktopLink = Model.Area.Item?.GetLink("HeaderDesktop") ?? null; 67 var headerMobileLink = Model.Area.Item?.GetLink("HeaderMobile") ?? null; 68 69 var footerDesktopLink = Model.Area.Item?.GetLink("FooterDesktop") ?? null; 70 var footerMobileLink = Model.Area.Item?.GetLink("FooterMobile") ?? null; 71 72 var disableWideBreakpoints = Model.Area?.Item?.GetRawValueString("DisableWideBreakpoints", "default"); 73 74 //string customHeaderInclude = !string.IsNullOrEmpty(Model.Area.Item.GetRawValueString("CustomHeaderInclude")) ? Model.Area.Item.GetFile("CustomHeaderInclude").Name : string.Empty; 75 string customHeaderInclude = !string.IsNullOrEmpty(Model.Area.Item.GetRawValueString("CustomHeaderInclude")) ? Model.Area.Item.GetRawValueString("CustomHeaderInclude").Split('/').Last() : string.Empty; 76 77 78 var themesParagraphLastChanged = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(themePageId).OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault(); 79 var cssLastModified = brandingPage.Audit.LastModifiedAt > themesParagraphLastChanged.Audit.LastModifiedAt ? brandingPage.Audit.LastModifiedAt : themesParagraphLastChanged.Audit.LastModifiedAt; 80 81 var cssThemeAndBrandingStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css")); 82 83 84 if (cssPageId != 0) 85 { 86 var cssFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath($"/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_css_styles_{Model.Area.ID}.css")); 87 var cssParagraphLastChanged = Dynamicweb.Content.Services.Paragraphs.GetParagraphsByPageId(cssPageId).OrderByDescending(p => p.Audit.LastModifiedAt).FirstOrDefault(); 88 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < cssParagraphLastChanged.Audit.LastModifiedAt) 89 { 90 var cssPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(cssPageId); 91 cssPageview.Redirect = false; 92 cssPageview.Output(); 93 } 94 } 95 96 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < brandingPage.Audit.LastModifiedAt) 97 { 98 //Branding page has been saved or the file is missing. Rewrite the file to disc. 99 if (brandingPageId > 0) 100 { 101 var brandingPageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(brandingPageId); 102 brandingPageview.Redirect = false; 103 brandingPageview.Output(); 104 } 105 } 106 107 if (!cssThemeAndBrandingStyleFileInfo.Exists || cssThemeAndBrandingStyleFileInfo.LastWriteTime < themesParagraphLastChanged.Audit.LastModifiedAt) 108 { 109 //Branding page has been saved or the file is missing. Rewrite the file to disc. 110 if (themePageId > 0) 111 { 112 var themePageview = Dynamicweb.Frontend.PageView.GetPageviewByPageID(themePageId); 113 themePageview.Redirect = false; 114 themePageview.Output(); 115 } 116 } 117 118 // Schema.org details for PDP 119 bool isProductDetailsPage = Dynamicweb.Context.Current.Request.QueryString.AllKeys.Contains("ProductID"); 120 bool isArticlePage = Model.ItemType == "Swift_Article"; 121 string schemaOrgType = string.Empty; 122 123 if (isProductDetailsPage) 124 { 125 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Product\""; 126 } 127 128 if (isArticlePage) 129 { 130 schemaOrgType = "itemscope=\"\" itemtype=\"https://schema.org/Article\""; 131 } 132 133 134 var cssStyleFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/styles.css")); 135 var cssStyleFileInfoCustom = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/css/custom.css")); 136 var jsFileInfo = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/scripts.js")); 137 var jsFileInfoCustom = new System.IO.FileInfo(Dynamicweb.Core.SystemInformation.MapPath("/Files/Templates/Designs/Swift/Assets/js/custom.js")); 138 139 string masterTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("Theme")) ? " theme " + Model.Area.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 140 141 string favicon = Model.Area.Item.GetRawValueString("Favicon", "/Files/Templates/Designs/Swift/Assets/Images/favicon.png"); 142 string appleTouchIcon = Model.Area.Item.GetRawValueString("AppleTouchIcon", "/Files/Templates/Designs/Swift/Assets/Images/apple-touch-icon.png"); 143 144 string headerCssClass = "sticky-top"; 145 bool movePageBehind = false; 146 147 string customScript = ""; 148 149 150 if (Model.PropertyItem != null) 151 { 152 customScript = Model.PropertyItem.GetRawValueString("CustomScript", ""); 153 154 headerCssClass = Model.PropertyItem.GetRawValueString("MoveThisPageBehindTheHeader", "sticky-top"); 155 movePageBehind = headerCssClass == "fixed-top" && !Pageview.IsVisualEditorMode ? true : false; 156 } 157 158 headerCssClass = headerCssClass == "" ? "sticky-top" : headerCssClass; 159 headerCssClass = Pageview.IsVisualEditorMode ? "" : headerCssClass; 160 161 string googleTagManagerID = Model.Area.Item.GetString("GoogleTagManagerID").Trim(); 162 string googleAnalyticsMeasurementID = Model.Area.Item.GetString("GoogleAnalyticsMeasurementID").Trim(); 163 164 bool allowTracking = AllowTracking(); 165 166 string klaviyoID = Model.Area.Item.GetString("KlaviyoPublicKey"); 167 168 string facebookPixel = Model.Area.Item.GetString("FacebookPixel"); 169 170 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/styles.css?{cssStyleFileInfo.LastWriteTime.Ticks}>; rel=preload; as=style;"); 171 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/css/custom.css?{cssStyleFileInfoCustom.LastWriteTime.Ticks}>; rel=preload; as=style;"); 172 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_{Model.Area.ID}.min.css?{cssLastModified.Ticks}>; rel=preload; as=style;"); 173 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/scripts.js?{jsFileInfo.LastWriteTime.Ticks}>; rel=preload; as=script;"); 174 Dynamicweb.Context.Current.Response.AddHeader("link", $"</Files/Templates/Designs/Swift/Assets/js/custom.js?{jsFileInfoCustom.LastWriteTime.Ticks}>; rel=preload; as=script;"); 175 176 177 SetMetaTags(); 178 179 List<Dynamicweb.Content.Page> languages = new List<Dynamicweb.Content.Page>(); 180 181 var masterPage = Pageview.Area.IsMaster ? Pageview.Page : Pageview.Page.MasterPage; 182 languages.Add(masterPage); 183 if (masterPage?.Languages != null) 184 { 185 foreach (var language in masterPage.Languages) 186 { 187 languages.Add(language); 188 } 189 } 190 191 Uri url = Dynamicweb.Context.Current.Request.Url; 192 string hostName = url.Host; 193 194 <!doctype html> 195 <html lang="@Pageview.Area.CultureInfo.TwoLetterISOLanguageName"> 196 <head> 197 <!-- @swiftVersion --> 198 @* Required meta tags *@ 199 <meta charset="utf-8"> 200 <meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0"> 201 <link rel="shortcut icon" href="@favicon"> 202 <link rel="apple-touch-icon" href="@appleTouchIcon"> 203 204 @Model.MetaTags 205 206 @{ 207 var alreadyWrittenTwoletterIsos = new List<string>(); 208 @* Languages meta data *@ 209 foreach (var language in languages) 210 { 211 hostName = url.Host; 212 if (language?.Area != null) 213 { 214 if (language.Area?.MasterArea != null && !string.IsNullOrEmpty(language.Area.MasterArea.DomainLock)) 215 { 216 hostName = language.Area.MasterArea.DomainLock; //dk.domain.com or dk-domain.dk 217 } 218 if (language != null && language.Area != null && language.Published && language.Area.Active && language.Area.Published) 219 { 220 if (!string.IsNullOrEmpty(language.Area.DomainLock)) 221 { 222 hostName = language.Area.DomainLock; //dk.domain.com or dk-domain.dk 223 } 224 string querystring = $"Default.aspx?ID={language.ID}"; 225 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["GroupID"])) 226 { 227 querystring += $"&GroupID={Dynamicweb.Context.Current.Request.QueryString["GroupID"]}"; 228 } 229 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"])) 230 { 231 querystring += $"&ProductID={Dynamicweb.Context.Current.Request.QueryString["ProductID"]}"; 232 } 233 if (!string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["VariantID"])) 234 { 235 querystring += $"&VariantID={Dynamicweb.Context.Current.Request.QueryString["VariantID"]}"; 236 } 237 238 string friendlyUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(querystring); 239 if (language.Area.RedirectFirstPage && language.ParentPageId == 0 && language.Sort == 1) 240 { 241 friendlyUrl = "/"; 242 } 243 string href = $"{url.Scheme}://{hostName}{friendlyUrl}"; 244 245 246 <link rel="alternate" hreflang="@language.Area.CultureInfo.Name.ToLower()" href="@href"> 247 if (!alreadyWrittenTwoletterIsos.Contains(language.Area.CultureInfo.TwoLetterISOLanguageName)) 248 { 249 alreadyWrittenTwoletterIsos.Add(language.Area.CultureInfo.TwoLetterISOLanguageName); 250 <link rel="alternate" hreflang="@language.Area.CultureInfo.TwoLetterISOLanguageName.ToLower()" href="@href"> 251 } 252 } 253 } 254 } 255 } 256 257 <title>@Model.Title</title> 258 @* Bootstrap + Swift stylesheet *@ 259 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css?@cssStyleFileInfo.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css"> 260 <link href="/Files/Templates/Designs/Swift/Assets/css/custom.css?@cssStyleFileInfoCustom.LastWriteTime.Ticks" rel="stylesheet" media="all" type="text/css"> 261 262 @if (disableWideBreakpoints != "disableBoth") 263 { 264 <style> 265 @@media ( min-width: 1600px ) { 266 .container-xxl, 267 .container-xl, 268 .container-lg, 269 .container-md, 270 .container-sm, 271 .container { 272 max-width: 1520px; 273 } 274 } 275 </style> 276 277 278 279 if (disableWideBreakpoints != "disableUltraWideOnly") 280 { 281 <style> 282 @@media ( min-width: 1920px ) { 283 .container-xxl, 284 .container-xl, 285 .container-lg, 286 .container-md, 287 .container-sm, 288 .container { 289 max-width: 1820px; 290 } 291 } 292 </style> 293 } 294 } 295 296 @* Branding and Themes min stylesheet *@ 297 <link href="/Files/Templates/Designs/Swift/_parsed/Swift_css/Swift_styles_@(Model.Area.ID).min.css?@cssLastModified.Ticks" rel="stylesheet" media="all" type="text/css" data-last-modified-content="@cssLastModified"> 298 <script src="/Files/Templates/Designs/Swift/Assets/js/scripts.js?@jsFileInfo.LastWriteTime.Ticks"></script> 299 <script src="/Files/Templates/Designs/Swift/Assets/js/custom.js?@jsFileInfoCustom.LastWriteTime.Ticks"></script> 300 <script type="module"> 301 swift.Scroll.hideHeadersOnScroll(); 302 swift.Scroll.handleAlternativeTheme(); 303 304 //Only load if AOS 305 const aosColumns = document.querySelectorAll('[data-aos]'); 306 if (aosColumns.length > 0) { 307 swift.AssetLoader.Load('/Files/Templates/Designs/Swift/Assets/js/aos.js?@jsFileInfo.LastWriteTime.Ticks', 'js'); 308 document.addEventListener('load.swift.assetloader', function () { 309 AOS.init({ duration: 400, delay: 100, easing: 'ease-in-out', mirror: false, disable: window.matchMedia('(prefers-reduced-motion: reduce)') }); 310 }); 311 } 312 </script> 313 314 @* Google gtag method - always include even if it is not used for anything *@ 315 <script> 316 window.dataLayer = window.dataLayer || []; 317 function gtag() { dataLayer.push(arguments); } 318 </script> 319 @* Google tag manager *@ 320 @if (!string.IsNullOrWhiteSpace(googleTagManagerID)) 321 { 322 @*<script> 323 gtag('consent', 'default', { 324 'ad_storage': 'denied', 325 'ad_user_data': 'denied', 326 'ad_personalization': 'denied', 327 'analytics_storage': 'denied' 328 }); 329 </script>*@ 330 <script> 331 (function (w, d, s, l, i) { 332 w[l] = w[l] || []; w[l].push({ 333 'gtm.start': 334 new Date().getTime(), event: 'gtm.js' 335 }); var f = d.getElementsByTagName(s)[0], 336 j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : ''; j.async = true; j.src = 337 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f); 338 })(window, document, 'script', 'dataLayer', '@(googleTagManagerID)'); 339 </script> 340 if (allowTracking) 341 { 342 string adConsent = GetCookieOptInPermission("Marketing"); 343 string analyticsConsent = GetCookieOptInPermission("Statistical"); 344 @*<script> 345 gtag('consent', 'update', { 346 'ad_storage': '@adConsent', 347 'ad_user_data': '@adConsent', 348 'ad_personalization': '@adConsent', 349 'analytics_storage': '@analyticsConsent' 350 }); 351 </script>*@ 352 353 354 } 355 } 356 357 @if (!string.IsNullOrWhiteSpace(facebookPixel) && allowTracking && GetCookieOptInPermission("Marketing") == "granted") 358 { 359 <!-- Facebook Pixel Code --> 360 <script> 361 !function(f,b,e,v,n,t,s) 362 {if(f.fbq)return;n=f.fbq=function(){n.callMethod? 363 n.callMethod.apply(n,arguments):n.queue.push(arguments)}; 364 if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; 365 n.queue=[];t=b.createElement(e);t.async=!0; 366 t.src=v;s=b.getElementsByTagName(e)[0]; 367 s.parentNode.insertBefore(t,s)}(window, document,'script', 368 'https://connect.facebook.net/en_US/fbevents.js'); 369 fbq('init', '@(facebookPixel)'); 370 fbq('track', 'PageView'); 371 </script> 372 <noscript> 373 <img height="1" width="1" style="display:none" 374 src="https://www.facebook.com/tr?id=@(facebookPixel)&ev=PageView&noscript=1"/> 375 </noscript> 376 <!-- End Facebook Pixel Code --> 377 378 } 379 380 381 382 @if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking) 383 { 384 var GoogleAnalyticsDebugMode = ""; 385 386 if (Model.Area.Item.GetBoolean("EnableGoogleAnalyticsDebugMode")) 387 { 388 GoogleAnalyticsDebugMode = ", {'debug_mode': true}"; 389 } 390 391 <script async src="https://www.googletagmanager.com/gtag/js?id=@googleAnalyticsMeasurementID"></script> 392 <script> 393 gtag('js', new Date()); 394 gtag('config', '@googleAnalyticsMeasurementID'@GoogleAnalyticsDebugMode); 395 </script> 396 } 397 398 @if (!string.IsNullOrWhiteSpace(klaviyoID)){ 399 <script type="text/javascript" async="" src="https://static.klaviyo.com/onsite/js/klaviyo.js?company_id=@(klaviyoID)"></script> 400 401 <script> 402 !function(){if(!window.klaviyo){window._klOnsite=window._klOnsite||[];try{window.klaviyo=new Proxy({},{get:function(n,i){return"push"===i?function(){var n;(n=window._klOnsite).push.apply(n,arguments)}:function(){for(var n=arguments.length,o=new Array(n),w=0;w<n;w++)o[w]=arguments[w];var t="function"==typeof o[o.length-1]?o.pop():void 0,e=new Promise((function(n){window._klOnsite.push([i].concat(o,[function(i){t&&t(i),n(i)}]))}));return e}}})}catch(n){window.klaviyo=window.klaviyo||[],window.klaviyo.push=function(){var n;(n=window._klOnsite).push.apply(n,arguments)}}}}(); 403 </script> 404 405 if (Pageview?.User?.ID != null){ 406 407 string userEmail = Dynamicweb.Core.Converter.ToString(Pageview.User?.Email); 408 string userName = Dynamicweb.Core.Converter.ToString(Pageview.User?.Name); 409 410 <script> 411 klaviyo.identify({ 412 '$email' : '@(userEmail)', 413 '$first_name' : '@(userName)' 414 }); 415 </script> 416 417 } 418 } 419 420 @if (!string.IsNullOrWhiteSpace(customScript)){ 421 @(customScript) 422 } 423 424 @if (!string.IsNullOrWhiteSpace(customHeaderInclude)) 425 { 426 @RenderPartial($"Components/Custom/{customHeaderInclude}") 427 } 428 </head> 429 <body class="brand @(masterTheme)" id="page@(Model.ID)"> 430 431 @* Google tag manager *@ 432 @if (!string.IsNullOrWhiteSpace(googleTagManagerID) && allowTracking) 433 { 434 <noscript> 435 <iframe src="https://www.googletagmanager.com/ns.html?id=@(googleTagManagerID)" 436 height="0" width="0" style="display:none;visibility:hidden"></iframe> 437 </noscript> 438 } 439 440 @if (renderAsResponsive || !renderMobile) 441 { 442 <header class="page-header @headerCssClass top-0@(responsiveClassDesktop)" id="page-header-desktop"> 443 @if (headerDesktopLink != null) 444 { 445 @RenderGrid(headerDesktopLink.PageId) 446 } 447 </header> 448 } 449 450 @if ((renderAsResponsive || renderMobile)) 451 { 452 <header class="page-header @headerCssClass top-0@(responsiveClassMobile)" id="page-header-mobile"> 453 @if (headerMobileLink != null) 454 { 455 @RenderGrid(headerMobileLink.PageId) 456 } 457 </header> 458 } 459 460 <div data-intersect></div> 461 462 <main id="content" @(schemaOrgType)> 463 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.PageViewModel> 464 @using System 465 @using Dynamicweb.Ecommerce.ProductCatalog 466 467 468 @{ 469 string productIdFromUrl = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : string.Empty; 470 bool isProductDetail = !string.IsNullOrEmpty(productIdFromUrl) && Pageview.Page.NavigationTag.ToLower() == "shop"; 471 472 bool isArticlePagePage = Model.ItemType == "Swift_Article"; 473 bool isArticleListPage = Model.ItemType == "Swift_ArticleListPage"; 474 string schemaOrgProp = string.Empty; 475 if(isArticlePagePage) 476 { 477 schemaOrgProp = "itemprop=\"articleBody\""; 478 } 479 480 string theme = ""; 481 string gridContent = ""; 482 483 if (Model.PropertyItem != null) 484 { 485 theme = !string.IsNullOrWhiteSpace(Model.PropertyItem.GetRawValueString("Theme")) ? "theme " + Model.PropertyItem.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 486 } 487 488 if (Model.Item != null || Pageview.IsVisualEditorMode) 489 { 490 if (!isProductDetail) 491 { 492 gridContent = Model.Grid("Grid", "Grid", "default:true;sort:1", "Page"); 493 } 494 else 495 { 496 var productObject = Dynamicweb.Ecommerce.Services.Products.GetProductById(productIdFromUrl, "", Pageview.Area.EcomLanguageId); 497 var detailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(productObject.PrimaryGroupId)?.Meta.PrimaryPage ?? string.Empty; 498 var detailPageId = detailPage != string.Empty ? Convert.ToInt16(detailPage.Substring(detailPage.LastIndexOf('=') + 1)) : GetPageIdByNavigationTag("ProductDetailPage"); 499 500 @RenderGrid(detailPageId) 501 } 502 } 503 504 bool doNotRenderPage = false; 505 506 //Check if we are on the poduct detail page, and if there is data to render 507 ProductViewModel product = new ProductViewModel(); 508 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 509 { 510 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 511 if (string.IsNullOrEmpty(product.Id)) { 512 doNotRenderPage = true; 513 } 514 } 515 516 //Render the page 517 if (!doNotRenderPage) { 518 string itemIdentifier = Model?.Item?.SystemName != null ? "item_" + Model.Item.SystemName.ToLower() : "item_Swift_Page"; 519 520 if (Pageview.IsVisualEditorMode) { 521 @Model.Placeholder("dwcontent", "content", "default:true;sort:1") 522 } 523 524 <div class="@theme @itemIdentifier" @schemaOrgProp> 525 @if (isArticleListPage) 526 { 527 var hx = $"hx-get=\"{Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Model.ID)}\" hx-select=\"#content\" hx-target=\"#content\" hx-swap=\"outerHTML\" hx-trigger=\"change\" hx-headers='{{\"feed\": \"true\"}}' hx-push-url=\"true\" hx-indicator=\"#ArticleFacetForm\""; 528 529 <form @hx id="ArticleFacetForm"> 530 @gridContent 531 </form> 532 <script type="module" src="/Files/Templates/Designs/Swift/Assets/js/htmx.js"></script> 533 <script type="module"> 534 document.addEventListener('htmx:confirm', (event) => { 535 let filters = event.detail.elt.querySelectorAll('select'); 536 for (var i = 0; i < filters.length; i++) { 537 let input = filters[i]; 538 if (input.name && !input.value) { 539 input.name = ''; 540 } 541 } 542 }); 543 544 document.addEventListener('htmx:beforeOnLoad', (event) => { 545 swift.Scroll.stopIntersectionObserver(); 546 }); 547 548 document.addEventListener('htmx:afterOnLoad', () => { 549 swift.Scroll.hideHeadersOnScroll(); 550 swift.Scroll.handleAlternativeTheme(); 551 }); 552 </script> 553 } 554 else 555 { 556 @gridContent 557 } 558 </div> 559 560 } else { 561 <div class="container"> 562 <div class="alert alert-info" role="alert">@Translate("Sorry. There is nothing to view here")</div> 563 </div> 564 } 565 566 if (!Model.IsCurrentUserAllowed) 567 { 568 int signInPage = GetPageIdByNavigationTag("SignInPage"); 569 int dashboardPage = GetPageIdByNavigationTag("MyAccountDashboardPage"); 570 571 if (!Pageview.IsVisualEditorMode) 572 { 573 if (signInPage != 0) 574 { 575 if (signInPage != Model.ID) { 576 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + signInPage); 577 } else { 578 if (dashboardPage != 0) { 579 Dynamicweb.Context.Current.Response.Redirect("/Default.aspx?ID=" + dashboardPage); 580 } else { 581 Dynamicweb.Context.Current.Response.Redirect("/"); 582 } 583 } 584 } 585 else 586 { 587 <div class="alert alert-dark m-0" role="alert"> 588 <span>@Translate("You do not have access to this page")</span> 589 </div> 590 } 591 } 592 else 593 { 594 <div class="alert alert-dark m-0" role="alert"> 595 <span>@Translate("To work on this page, you must be signed in, in the frontend")</span> 596 </div> 597 } 598 } 599 } 600 601 <script> 602 // Listen for the event. 603 604 function delay(time) { 605 return new Promise(resolve => setTimeout(resolve, time)); 606 } 607 608 function runKlaviyo(){ 609 let scr = document.createElement('script'); 610 let el = document.getElementById("AddedToCart"); 611 scr.setAttribute("id", "tempAddedToCart"); 612 scr.innerHTML = el.innerHTML; 613 document.body.appendChild(scr); 614 document.getElementById("tempAddedToCart").outerHTML = ""; 615 } 616 617 document.addEventListener( 618 "updated.swift.cart", 619 (e) => { 620 delay(200).then(() => runKlaviyo()); 621 }, 622 false, 623 ); 624 625 </script> 626 </main> 627 628 @if (renderAsResponsive || !renderMobile) 629 { 630 <footer class="page-footer@(responsiveClassDesktop)" id="page-footer-desktop"> 631 @if (footerDesktopLink != null) 632 { 633 @RenderGrid(footerDesktopLink.PageId) 634 } 635 </footer> 636 } 637 638 @if (renderAsResponsive || renderMobile) 639 { 640 <footer class="page-footer@(responsiveClassMobile)" id="page-footer-mobile"> 641 @if (footerMobileLink != null) 642 { 643 @RenderGrid(footerMobileLink.PageId) 644 } 645 </footer> 646 } 647 648 @* Render any offcanvas menu here *@ 649 @RenderSnippet("offcanvas") 650 651 @{ 652 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"]); 653 } 654 655 @* Language selector modal *@ 656 <div class="modal fade" id="PreferencesModal" tabindex="-1" aria-hidden="true"> 657 <div class="modal-dialog modal-dialog-centered modal-sm" id="PreferencesModalContent"> 658 @* The content here comes from an external request *@ 659 </div> 660 </div> 661 662 @* Favorite toast *@ 663 <div aria-live="polite" aria-atomic="true"> 664 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 11"> 665 <div id="favoriteNotificationToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true"> 666 <div class="toast-header"> 667 <strong class="me-auto">@Translate("Favorite list updated")</strong> 668 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button> 669 </div> 670 <div class="toast-body d-flex gap-3"> 671 <div id="favoriteNotificationToast_Image"></div> 672 <div id="favoriteNotificationToast_Text"></div> 673 </div> 674 </div> 675 </div> 676 </div> 677 678 @* Modal for dynamic content *@ 679 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true"> 680 <div class="modal-dialog modal-dialog-centered modal-md"> 681 <div class="modal-content theme light" id="DynamicModalContent"> 682 @* The content here comes from an external request *@ 683 </div> 684 </div> 685 </div> 686 687 @* Offcanvas for dynamic content *@ 688 <div class="offcanvas offcanvas-end theme light" tabindex="-1" id="DynamicOffcanvas"> 689 @* The content here comes from an external request *@ 690 </div> 691 692 @if (Model.Area.Item.GetBoolean("ShowErpDownMessage") && !Dynamicweb.Core.Converter.ToBoolean(Context.Current.Items["IsWebServiceConnectionAvailable"])) 693 { 694 string erpDownMessageTheme = !string.IsNullOrWhiteSpace(Model.Area.Item.GetRawValueString("ErpDownMessageTheme")) ? " theme " + Model.Area.Item.GetRawValueString("ErpDownMessageTheme").Replace(" ", "").Trim().ToLower() : "theme light"; 695 696 <div class="position-fixed bottom-0 end-0 p-3" style="z-index: 1040"> 697 <div class="toast fade show border-0 @erpDownMessageTheme" role="alert" aria-live="assertive" aria-atomic="true"> 698 <div class="toast-header"> 699 <strong class="me-auto">@Translate("Connection down")</strong> 700 <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button> 701 </div> 702 <div class="toast-body"> 703 @Translate("We are experiencing some connectivity issues. Not all features may be available to you.") 704 </div> 705 </div> 706 </div> 707 } 708 709 @if (miniCartEnabled) 710 { 711 @* Open MiniCart when the cart is updated *@ 712 <script type="module"> 713 document.addEventListener('updated.swift.cart', (event) => { 714 let orderContext = event?.detail?.formData?.get("OrderContext"); 715 updateCartSummary(orderContext); 716 717 @if (offcanvasMiniCartBehaviour == "2" || offcanvasMiniCartBehaviour == "3") { 718 <text>openMiniCartOffcanvas();</text> 719 } 720 }); 721 </script> 722 723 if (offcanvasMiniCartBehaviour == "1" || offcanvasMiniCartBehaviour == "3") 724 { 725 @* Open MiniCart when toggle is clicked *@ 726 <script type="module"> 727 let miniCartToggles = document.querySelectorAll('.mini-cart-quantity'); 728 miniCartToggles?.forEach((toggle) => { 729 toggle.parentElement.addEventListener('click', (event) => { 730 event.preventDefault(); 731 let orderContext = toggle.dataset?.orderContext; 732 updateCartSummary(orderContext); 733 734 openMiniCartOffcanvas(); 735 }); 736 }); 737 </script> 738 } 739 740 <script> 741 742 const updateCartSummary = (orderContext) => { 743 const dynamicOffcanvas = document.getElementById('DynamicOffcanvas'); 744 swift.PageUpdater.UpdateFromUrlInline(event, '/Default.aspx?ID=@(cartSummaryPageId)&CartType=minicart&RequestPageID=@(Pageview.Page.ID)&OrderContext=' + orderContext +'', 'Swift_CartSummary.cshtml', dynamicOffcanvas); 745 }; 746 747 const openMiniCartOffcanvas = () => { 748 const dynamicOffcanvas = document.getElementById('DynamicOffcanvas'); 749 const miniCartOffcanvas = bootstrap.Offcanvas.getOrCreateInstance(dynamicOffcanvas); 750 dynamicOffcanvas.classList.add('overflow-y-auto'); 751 752 if (!miniCartOffcanvas._isShown) { 753 miniCartOffcanvas.show(); 754 hideActiveOffcanvases(miniCartOffcanvas); 755 } 756 }; 757 758 const hideActiveOffcanvases = (miniCartOffcanvas) => { 759 let activeOffcanvases = document.querySelectorAll('.offcanvas.show'); 760 activeOffcanvases?.forEach((offCanvas) => { 761 offCanvas = bootstrap.Offcanvas.getInstance(offCanvas); 762 if (offCanvas !== miniCartOffcanvas) { 763 offCanvas.hide(); 764 } 765 }); 766 }; 767 768 </script> 769 } 770 771 </body> 772 773 </html> 774 775 } 776 else if (Pageview.IsVisualEditorMode) 777 { 778 <head> 779 <title>@Model.Title</title> 780 @* Bootstrap + Swift stylesheet *@ 781 <link href="/Files/Templates/Designs/Swift/Assets/css/styles.css" rel="stylesheet" media="all" type="text/css"> 782 </head> 783 <body class="p-3"> 784 <div class="alert alert-danger" role="alert"> 785 @Translate("Basic Swift setup is needed!") 786 </div> 787 788 @if (brandingPage == null) 789 { 790 <div class="alert alert-warning" role="alert"> 791 @Translate("Please add a Branding page and reference it in website settings") 792 </div> 793 } 794 795 @if (themesParagraphs == null) 796 { 797 <div class="alert alert-warning" role="alert"> 798 @Translate("Please add a Themes collection page and reference it in website settings") 799 </div> 800 } 801 </body> 802 } 803 804 805 @functions { 806 void SetMetaTags() 807 { 808 //Verification Tokens 809 string siteVerificationGoogle = Model.Area.Item.GetString("Google_Site_Verification") != null ? Model.Area.Item.GetString("Google_Site_Verification") : ""; 810 811 //Generic Site Values 812 string openGraphFacebookAppID = Model.Area.Item.GetString("Fb_app_id") != null ? Model.Area.Item.GetString("Fb_app_id") : ""; 813 string openGraphType = Model.Area.Item.GetString("Open_Graph_Type") != null ? Model.Area.Item.GetString("Open_Graph_Type") : ""; 814 string openGraphSiteName = Model.Area.Item.GetString("Open_Graph_Site_Name") != null ? Model.Area.Item.GetString("Open_Graph_Site_Name") : ""; 815 816 string twitterCardSite = Model.Area.Item.GetString("Twitter_Site") != null ? Model.Area.Item.GetString("Twitter_Site") : ""; 817 818 //Page specific values 819 string openGraphSiteTitle = Model.Area.Item.GetString("Open_Graph_Title") != null ? Model.Area.Item.GetString("Open_Graph_Title") : ""; 820 FileViewModel openGraphImage = Model.Area.Item.GetFile("Open_Graph_Image"); 821 string openGraphImageALT = Model.Area.Item.GetString("Open_Graph_Image_ALT") != null ? Model.Area.Item.GetString("Open_Graph_Image_ALT") : ""; 822 string openGraphDescription = Model.Area.Item.GetString("Open_Graph_Description") != null ? Model.Area.Item.GetString("Open_Graph_Description") : ""; 823 824 string twitterCardURL = Model.Area.Item.GetString("Twitter_URL") != null ? Model.Area.Item.GetString("Twitter_URL") : ""; 825 string twitterCardTitle = Model.Area.Item.GetString("Twitter_Title") != null ? Model.Area.Item.GetString("Twitter_Title") : ""; 826 string twitterCardDescription = Model.Area.Item.GetString("Twitter_Description") != null ? Model.Area.Item.GetString("Twitter_Description") : ""; 827 FileViewModel twitterCardImage = Model.Area.Item.GetFile("Twitter_Image"); 828 string twitterCardImageALT = Model.Area.Item.GetString("Twitter_Image_ALT") != null ? Model.Area.Item.GetString("Twitter_Image_ALT") : ""; 829 string topImage = Pageview.Page.TopImage.StartsWith("/Files", StringComparison.OrdinalIgnoreCase) ? Pageview.Page.TopImage : $"/Files{Pageview.Page.TopImage}"; 830 831 832 833 if (string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString["ProductID"])) 834 { 835 if (!string.IsNullOrEmpty(Model.Description)) 836 { 837 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{Model.Description}\">"); 838 } 839 else 840 { 841 Pageview.Meta.AddTag($"<meta property=\"og:description\" content=\"{openGraphDescription}\">"); 842 } 843 844 if (!string.IsNullOrEmpty(Pageview.Page.TopImage)) 845 { 846 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{topImage}\">"); 847 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{topImage}\">"); 848 } 849 else if (openGraphImage != null) 850 { 851 Pageview.Meta.AddTag($"<meta property=\"og:image\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">"); 852 Pageview.Meta.AddTag($"<meta property=\"og:image:secure_url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}\">"); 853 } 854 855 if (!string.IsNullOrEmpty(openGraphImageALT)) 856 { 857 Pageview.Meta.AddTag($"<meta property=\"og:image:alt\" content=\"{openGraphImageALT}\">"); 858 } 859 if (!string.IsNullOrEmpty(twitterCardDescription)) 860 { 861 Pageview.Meta.AddTag("twitter:description", twitterCardDescription); 862 } 863 864 if (!string.IsNullOrEmpty(Pageview.Page.TopImage)) 865 { 866 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{topImage}"); 867 } 868 else if (twitterCardImage != null) 869 { 870 Pageview.Meta.AddTag("twitter:image", $"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{openGraphImage.Path}"); 871 } 872 873 if (!string.IsNullOrEmpty(twitterCardImageALT)) 874 { 875 Pageview.Meta.AddTag("twitter:image:alt", twitterCardImageALT); 876 } 877 } 878 879 if (!string.IsNullOrEmpty(siteVerificationGoogle)) 880 { 881 Pageview.Meta.AddTag("google-site-verification", siteVerificationGoogle); 882 } 883 884 if (!string.IsNullOrEmpty(openGraphFacebookAppID)) 885 { 886 Pageview.Meta.AddTag($"<meta property=\"fb:app_id\" content=\"{openGraphFacebookAppID}\">"); 887 } 888 889 if (!string.IsNullOrEmpty(openGraphType)) 890 { 891 Pageview.Meta.AddTag($"<meta property=\"og:type\" content=\"{openGraphType}\">"); 892 } 893 894 <!-- test System.Web.HttpContext.Current.Request.QueryString["ProductID"] Dynamicweb.Environment.IRequest.QueryString("ProductID") --> 895 896 897 if (!string.IsNullOrEmpty(openGraphSiteName)) 898 { 899 Pageview.Meta.AddTag($"<meta property=\"og:url\" content=\"{Dynamicweb.Context.Current.Request.Url.Scheme}://{Dynamicweb.Context.Current.Request.Url.Host}{Pageview.SearchFriendlyUrl}\">"); 900 } 901 902 if (!string.IsNullOrEmpty(openGraphSiteName)) 903 { 904 Pageview.Meta.AddTag($"<meta property=\"og:site_name\" content=\"{openGraphSiteName}\">"); 905 } 906 907 if (!string.IsNullOrEmpty(Model.Title)) 908 { 909 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{Model.Title}\">"); 910 } 911 else 912 { 913 Pageview.Meta.AddTag($"<meta property=\"og:title\" content=\"{openGraphSiteTitle}\">"); 914 } 915 916 if (!string.IsNullOrEmpty(twitterCardSite)) 917 { 918 Pageview.Meta.AddTag("twitter:site", twitterCardSite); 919 } 920 921 if (!string.IsNullOrEmpty(twitterCardURL)) 922 { 923 Pageview.Meta.AddTag("twitter:url", twitterCardURL); 924 } 925 926 if (!string.IsNullOrEmpty(twitterCardTitle)) 927 { 928 Pageview.Meta.AddTag("twitter:title", twitterCardTitle); 929 } 930 } 931 } 932