Error executing template "Designs/Swift/Paragraph/Swift_ProductAddToCart.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
at CompiledRazorTemplates.Dynamic.RazorEngine_d22e2ad7635e44a19c67004f27692a72.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()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel>
2 @using Dynamicweb.Ecommerce.ProductCatalog
3 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites
4 @using Proff1.Service
5 @using System.Text.Json
6 @using System.Linq
7
8
9 @{
10 ProductViewModel product = null;
11 List<Dynamicweb.Ecommerce.ProductCatalog.GroupInfoViewModel> productGroup = null;
12 string lastGroup = null;
13 string productIdTag = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : "";
14 var productService = new Dynamicweb.Ecommerce.Products.ProductService();
15 var regularProduct = productService.GetProductById(productIdTag, "", true);
16 var productBrand = regularProduct?.ProductFieldValues.GetProductFieldValue("TK_Brand").Value.ToString();
17
18
19 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
20 {
21 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
22 productGroup = product.GroupPaths[0];
23 lastGroup = productGroup.Last().Name;
24 }
25 else if (Pageview.Page.Item["DummyProduct"] != null)
26 {
27 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page);
28 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel();
29
30 if (productList?.Products is object)
31 {
32 product = productList.Products[0];
33 }
34 }
35
36 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", "");
37 bool anonymousUser = Pageview.User == null;
38 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Dynamicweb.Context.Current.Items["IsWebServiceConnectionAvailable"]);
39 bool hideAddToCart = anonymousUsersLimitations.Contains("cart") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHideAddToCart") && isErpConnectionDown;
40 hideAddToCart = Pageview.IsVisualEditorMode ? false : hideAddToCart;
41
42 string addedMessageId = $"addedMsg{product.Id}_{Pageview.CurrentParagraph.ID}";
43 string addToCartButtonId = $"AddToCartButton{product.Id}_{Pageview.CurrentParagraph.ID}";
44 }
45
46
47 @if (product is object && !hideAddToCart)
48 {
49 string horizontalAlign = Model.Item.GetRawValueString("HorizontalAlignment", "");
50 horizontalAlign = horizontalAlign == "center" ? "justify-content-center" : horizontalAlign;
51 horizontalAlign = horizontalAlign == "end" ? "justify-content-end" : horizontalAlign;
52 horizontalAlign = horizontalAlign == "full" ? "" : horizontalAlign;
53
54 bool favoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowAddToFavorites")) ? Model.Item.GetBoolean("ShowAddToFavorites") : false;
55 bool quantitySelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowQuantitySelector")) ? Model.Item.GetBoolean("ShowQuantitySelector") : false;
56 bool unitsSelector = !string.IsNullOrEmpty(Model.Item.GetString("ShowUnitsSelector")) ? Model.Item.GetBoolean("ShowUnitsSelector") : false;
57 bool hideInventory = !string.IsNullOrEmpty(Model.Item.GetString("HideInventory")) ? Model.Item.GetBoolean("HideInventory") : false;
58 bool hideStockState = !string.IsNullOrEmpty(Model.Item.GetString("HideStockState")) ? Model.Item.GetBoolean("HideStockState") : false;
59
60 string buttonSize = Model.Item.GetRawValueString("ButtonSize", "regular");
61 string inputSize = string.Empty;
62
63 switch (buttonSize)
64 {
65 case "small":
66 inputSize = " input-group-sm";
67 buttonSize = " btn-sm";
68 break;
69 case "regular":
70 buttonSize = string.Empty;
71 break;
72 case "large":
73 inputSize = " input-group-lg";
74 buttonSize = " btn-lg";
75 break;
76 }
77
78 string iconPath = "/Files/icons/";
79 string url = "/Default.aspx?ID=" + (GetPageIdByNavigationTag("CartService"));
80 if (!url.Contains("LayoutTemplate"))
81 {
82 url += url.Contains("?") ? "&LayoutTemplate=Swift_MiniCart.cshtml" : "?LayoutTemplate=Swift_MiniCart.cshtml";
83 }
84
85
86 bool isNeverOutOfStock = product.NeverOutOfstock;
87 var totalItemsInStock = Proff1Services.StockService.GetStockInfo(product.Number).Sum(stockInfo => stockInfo.ItemsInStock);
88 string disableAddToCart = (totalItemsInStock <= 0) ? "disabled" : "";
89
90
91 string addToCartButtonText = Translate("Add to cart");
92
93 if (!product.NeverOutOfstock && totalItemsInStock <= 0)
94 {
95 addToCartButtonText = Translate("Ikke på lager");
96 }
97 else if (totalItemsInStock <= 0)
98 {
99 addToCartButtonText = Translate("Bestill");
100 }
101
102 disableAddToCart = isNeverOutOfStock ? "" : disableAddToCart;
103
104 string whenVariantsExist = Model.Item.GetRawValueString("WhenVariantsExist", "hide");
105
106 string flexFill = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "flex-fill" : "";
107 string fullWidth = Model.Item.GetRawValueString("HorizontalAlignment", "") == "full" ? "w-100" : "";
108 string addToCartIcon = Model.Item.GetRawValueString("Icon", iconPath + "shopping-cart.svg");
109 string checkIcon = Model.Item.GetRawValueString("Icon", iconPath + "check.svg");
110 string addToCartLabel = !addToCartIcon.Contains("_none") ? "<span class=\"icon-2\">" + ReadFile(addToCartIcon) + "</span>" : "";
111 addToCartLabel += !addToCartIcon.Contains("_none") && !Model.Item.GetBoolean("HideButtonText") ? " " : "";
112 addToCartLabel += !Model.Item.GetBoolean("HideButtonText") ? addToCartButtonText : "";
113
114
115 string productId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("ProductID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("ProductID") : "";
116 bool isProductDetailsPage = !string.IsNullOrEmpty(productId);
117 bool isMasterWithVariant = product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId);
118
119 var deliveryDays = product.ProductFields["P1_Product_Delivery_Days"].Value;
120
121 if (product.VariantInfo.VariantInfo == null || isProductDetailsPage)
122 {
123 string unitId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("UnitId")) ? Dynamicweb.Context.Current.Request.Form.Get("UnitId") : product.DefaultUnitId;
124 if (string.IsNullOrEmpty(unitId) && product?.UnitOptions != null)
125 {
126 if (product.UnitOptions.FirstOrDefault<UnitOptionViewModel>() != null)
127 {
128 unitId = product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Id;
129 }
130 }
131
132 string minQty = product.PurchaseMinimumQuantity != 1 ? "min=\"" + product.PurchaseMinimumQuantity.ToString() + "\"" : "min=\"1\"";
133 string stepQty = product.PurchaseQuantityStep > 1 ? product.PurchaseQuantityStep.ToString() : "1";
134 string valueQty = product.PurchaseMinimumQuantity > product.PurchaseQuantityStep ? product.PurchaseMinimumQuantity.ToString() : stepQty;
135 disableAddToCart = product.VariantInfo.VariantInfo != null && string.IsNullOrEmpty(product.VariantId) ? "disabled" : disableAddToCart;
136
137 var reserveMode = Dynamicweb.Ecommerce.Frontend.Cart.ProductReserve.Mode;
138
139 if (unitsSelector && product.UnitOptions.Count > 0)
140 {
141 <form method="post" action="/Default.aspx?ID=@(Pageview.Page.ID)&ProductId=@product.Id" id="UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID">
142 <input type="hidden" name="redirect" value="false">
143 <input type="hidden" name="VariantID" value="@product.VariantId">
144 <input type="hidden" name="UnitID" class="js-unit-id" value="@unitId">
145 </form>
146 }
147
148 <div class="d-grid @horizontalAlign @fullWidth js-input-group item_@Model.Item.SystemName.ToLower()">
149 <form method="post" action="@url" class="@fullWidth" style="z-index: 1">
150 <input type="hidden" name="redirect" value="false">
151 <input type="hidden" name="ProductId" value="@product.Id">
152 <input type="hidden" name="ProductName" value="@product.Name">
153 <input type="hidden" name="ProductVariantName" value="@product.VariantName">
154 <input type="hidden" name="ProductCurrency" value="@Dynamicweb.Ecommerce.Common.Context.Currency.Code">
155 <input type="hidden" name="ProductPrice" value="@PriceViewModelExtensions.ToStringInvariant(product.Price)">
156 <input type="hidden" name="ProductReferer" value="component_ProductAddToCart">
157 <input type="hidden" name="cartcmd" value="add">
158
159 @if (reserveMode == Dynamicweb.Ecommerce.Frontend.Cart.ProductReserveMode.AddToCart)
160 {
161 <input type="hidden" name="GetReservedAmount" value="true">
162 }
163
164 @if (!string.IsNullOrEmpty(product.VariantId))
165 {
166 <input type="hidden" name="VariantId" value="@product.VariantId">
167 }
168
169 @if (!product.NeverOutOfstock)
170 {
171 <input type="hidden" name="Stock" value="@product.StockLevel">
172
173 <template class="js-out-of-stock-notice">
174 <div class="modal-header">
175 <h1 class="modal-title fs-5">@Translate("Stock limit")</h1>
176 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
177 </div>
178 <div class="modal-body">
179 @Translate("There are not enough products in stock. The product might be sold out or discontinued. Please adjust the quantity.")
180 </div>
181 </template>
182 }
183
184 @if (stepQty != "1")
185 {
186 <template class="js-step-quantity-warning">
187 <div class="modal-header">
188 <h1 class="modal-title fs-5">@Translate("The quantity is not valid")</h1>
189 </div>
190 <div class="modal-body">
191 @Translate("Please select a quantity that is dividable by") @stepQty
192 </div>
193 </template>
194 }
195 @if (product.PurchaseMinimumQuantity != 1)
196 {
197 <template class="js-min-quantity-warning">
198 <div class="modal-header">
199 <h1 class="modal-title fs-5">@Translate("The product could not be added to the cart")</h1>
200 </div>
201 <div class="modal-body">
202 @Translate("The quantity is not valid. You must buy at least") @product.PurchaseMinimumQuantity
203 </div>
204 </template>
205 }
206
207 @if (quantitySelector || (!anonymousUser && product.VariantInfo.VariantInfo != null) || (!anonymousUser && favoritesSelector))
208 {
209 <input type="hidden" id="Unit_@(product.Id)_@product.VariantId" name="UnitID" value="@unitId" />
210 }
211
212 <div class="d-flex flex-row w-100">
213 @if (!anonymousUser && favoritesSelector)
214 {
215 @RenderPartial("Components/ToggleFavorite.cshtml", product)
216 }
217
218 @if (!quantitySelector)
219 {
220 <input id="Quantity_@(product.Id)_@product.VariantId" name="Quantity" value="@valueQty" type="hidden" @disableAddToCart>
221 }
222
223 <div class="input-group input-primary-button-group flex-nowrap@(inputSize)">
224 @if (quantitySelector)
225 {
226 <div class="d-flex me-2" style="border: 1px solid #5555">
227 <button type="button" class="btn btn-stepper fs-6 fw-normal rounded-0" onclick="decreaseQuantity('Quantity_@(product.Id)_@product.VariantId')" style="border-right: 1px solid #5555">-</button>
228 <input id="Quantity_@(product.Id)_@product.VariantId" name="Quantity" value="@valueQty" step="@stepQty" @minQty class="form-control swift_quantity-field text-center border-white" style="max-width: 40px; z-index: 1" type="number" onchange="swift.Cart.UpdateOnEnterKey(event)" onkeyup="swift.Cart.UpdateOnEnterKey(event)" @disableAddToCart>
229 <button type="button" class="btn btn-stepper fs-6 fw-normal m-r-5 rounded-0" onclick="increaseQuantity('Quantity_@(product.Id)_@product.VariantId')" style="border-left: 1px solid #5555">+</button>
230 </div>
231 }
232
233 @if (unitsSelector && product.UnitOptions.Count > 0)
234 {
235 string selectedUnitName = !string.IsNullOrEmpty(unitId) && product?.UnitOptions != null ? unitId : product.UnitOptions.FirstOrDefault<UnitOptionViewModel>().Name;
236
237 foreach (var unitOption in product.UnitOptions)
238 {
239 if (unitOption.Id == unitId)
240 {
241 selectedUnitName = unitOption.Name;
242 }
243 }
244
245 <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
246 @selectedUnitName
247 </button>
248 <ul class="dropdown-menu swift_unit-field">
249 @foreach (var unitOption in product.UnitOptions)
250 {
251 var selectedUnit = unitOption.Id == unitId ? "selected" : "";
252
253 <li>
254 <button type="button" class="btn dropdown-item" data-value="@unitOption.Id" onclick="document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID').querySelector('.js-unit-id').value = this.getAttribute('data-value');
255 document.querySelector('#Unit_@(product.Id)_@product.VariantId').value = this.getAttribute('data-value');
256 swift.PageUpdater.Update(document.querySelector('#UnitSelectorForm_@(product.Id)_@(product.VariantId)_@Model.ID'))">
257 <span>@unitOption.Name</span>
258 <span>
259 @if (unitOption.StockLevel > 0)
260 {
261 if (!Model.Item.GetBoolean("HideInventory"))
262 {
263 <span class="small text-success">@unitOption.StockLevel @Translate("In stock")</span>
264 }
265 else
266 {
267 <span class="small text-success">@Translate("In stock")</span>
268 }
269 }
270 else
271 {
272 <span class="small text-danger">@Translate("Out of Stock")</span>
273 }
274 </span>
275 </button>
276 </li>
277 }
278 </ul>
279 }
280
281 <div>
282 <button type="button" onclick="swift.Cart.Update(event)" class="btn btn-primary @(buttonSize) @flexFill js-add-to-cart-button rounded " style="white-space: nowrap; font-size: 0.9rem;" @disableAddToCart title="@Translate("Add to cart")" id="@addToCartButtonId">
283 @if (!Model.Item.GetBoolean("HideButtonText"))
284 {
285 <span class="text-nowrap d-flex align-items-center justify-content-center gap-2">
286 @addToCartLabel
287 </span>
288
289 }
290 else
291 {
292 @addToCartLabel
293 }
294 </button>
295
296 @if (isProductDetailsPage)
297 {
298
299 <p class="position-absolute top-100 mt-2 pb-2 d-none" id="addedMsg@(product.Id)_@Pageview.CurrentParagraph.ID">@Translate("Lagt i handlekurv")</p>
300 }
301 else
302 {
303 <p class="position-absolute top-100 end-0 mt-2 pb-2 d-none" id="addedMsg@(product.Id)_@Pageview.CurrentParagraph.ID">@Translate("Lagt i handlekurv")</p>
304
305 }
306 </div>
307
308
309 </div>
310 </div>
311 </form>
312 @if (isProductDetailsPage && !isMasterWithVariant)
313 {
314 <div class="stock-status py-2">
315 <span class="stock-label text-decoration-underline">Lagerstatus</span>
316
317 <div class="stock-info">
318
319 @foreach (var stockInfo in Proff1Services.StockService.GetStockInfo(product.Number))
320 {
321 <span>@stockInfo.LocationName: @stockInfo.ItemsInStock</span><br />
322 }
323
324 </div>
325 </div>
326 <div class="stock-status pt-3">
327 @if (totalItemsInStock <= 0)
328 {
329
330
331 if (Convert.ToInt32(deliveryDays) > 0)
332 {
333 <p class="m-0 small d-flex align-items-center lh-1">
334 <span class="bg-danger me-2 stock__dot"></span>@Translate("Order item - Expected delivery time") @deliveryDays @Translate("days")
335 </p>
336 }
337 else
338 {
339 <p class="m-0 small d-flex align-items-center lh-1">
340 <span class="bg-danger me-2 stock__dot"></span>@Translate("Order item - Expected delivery time unknown, please contact us")
341 </p>
342 }
343
344 }
345 else if (totalItemsInStock <= 4)
346 {
347
348 <p class="m-0 small d-flex align-items-center lh-1">
349 <span class="bg-warning me-2 stock__dot"></span>@Translate("5 In Stock")
350 </p>
351 }
352 else if (totalItemsInStock <= 9)
353 {
354 <p class="m-0 small d-flex align-items-center lh-1">
355 <span class="bg-success me-2 stock__dot"></span>@Translate("5-10 In Stock")
356 </p>
357 }
358 else if (totalItemsInStock <= 99)
359 {
360 <p class="m-0 small d-flex align-items-center lh-1">
361 <span class="bg-success me-2 stock__dot"></span>@Translate("10 In Stock")
362 </p>
363 }
364 else if (totalItemsInStock >= 100)
365 {
366 <p class="m-0 small d-flex align-items-center lh-1">
367 <span class="bg-success me-2 stock__dot"></span>@Translate("100+ In Stock")
368 </p>
369 }
370 </div>
371 }
372 else if (isProductDetailsPage && isMasterWithVariant)
373 {
374 <div class="stock-status pt-3">
375 <p class="m-0 small d-flex align-items-center lh-1">
376 @Translate("Choose a product/variant to see stock status")
377 </p>
378 </div>
379 }
380
381 </div>
382
383
384 }
385 else
386 {
387 string buttonText = Translate("Select");
388
389 string variantSelectorServicePageId = !string.IsNullOrEmpty(Model.Item.GetString("VariantSelectorServicePageId")) ? Model.Item.GetLink("VariantSelectorServicePageId").PageId.ToString() : "";
390 variantSelectorServicePageId = variantSelectorServicePageId != "" ? variantSelectorServicePageId : GetPageIdByNavigationTag("VariantSelectorService").ToString();
391 string link = product.GetProductLink(GetPageIdByNavigationTag("Shop"), false);
392
393 <div class="d-flex @horizontalAlign w-100 item_@Model.Item.SystemName.ToLower()">
394 @if (!anonymousUser && favoritesSelector)
395 {
396 @RenderPartial("Components/ToggleFavorite.cshtml", product)
397 }
398 <form action="/Default.aspx?ID=@variantSelectorServicePageId" data-response-target-element="DynamicModalContent" data-preloader="inline" style="z-index: 1" class="@fullWidth">
399 <input type="hidden" name="ProductID" value="@product.Id">
400 <input type="hidden" name="QuantitySelector" value="@quantitySelector.ToString()">
401 <input type="hidden" name="HideInventory" value="@hideInventory.ToString()">
402 <input type="hidden" name="HideStockState" value="@hideStockState.ToString()">
403 <input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId">
404 <input type="hidden" name="ViewType" value="ModalContent">
405 <a href="@link" class="btn btn-primary" title="@Translate("Select")">@buttonText</a>
406 </form>
407 </div>
408 }
409 }
410 else if (Pageview.IsVisualEditorMode)
411 {
412 <div class="alert alert-dark m-0">@Translate("No products available")</div>
413 }
414
415 @{
416 var text = "available online and in store.";
417 var translated = @Translate(text);
418 string metaDescription = $"Vi har {(string.IsNullOrEmpty(productBrand) ? "" : productBrand + " ")}{product.Name} {translated} Proff1 hjelper deg med {lastGroup}.";
419 string metaTitle = $"{(string.IsNullOrEmpty(productBrand) ? "" : productBrand + " ")}{product.Name}";
420 }
421
422 <script>
423
424 function decreaseQuantity(inputId) {
425 const input = document.getElementById(inputId);
426 const currentValue = parseInt(input.value);
427
428 if (currentValue > 1) {
429 input.value = currentValue - 1;
430 }
431 }
432
433 function increaseQuantity(inputId) {
434 const input = document.getElementById(inputId);
435 const currentValue = parseInt(input.value);
436
437 input.value = currentValue + 1;
438 }
439
440 function UpdateCart(productId) {
441
442 }
443
444
445 var addToCartButton = document.getElementById("@addToCartButtonId");
446
447 if (addToCartButton) {
448
449 addToCartButton.addEventListener('click', UpdateCart);
450 }
451 </script>
452
453
454 <script>
455 (function () {
456 const BTN_ID = "@addToCartButtonId";
457 const MSG_ID = "@addedMessageId";
458
459 const firedOnce = new Set();
460
461 function trackAddToCart(payload) {
462 const { productId, qty, unitPriceInclVat, lineValueInclVat, currency } = payload;
463 if (!productId) return;
464
465 if (firedOnce.has(productId)) return;
466
467 console.log("Meta Pixel - AddToCart", payload);
468
469 if (typeof fbq === "function") {
470 fbq('track', 'AddToCart', {
471 content_ids: [productId],
472 content_type: 'product',
473 value: lineValueInclVat,
474 currency,
475 contents: [{ id: productId, quantity: qty, item_price: unitPriceInclVat }]
476 });
477 }
478
479 firedOnce.add(productId);
480 setTimeout(() => firedOnce.delete(productId), 1000);
481 }
482
483 function onAddToCartClick(e) {
484 const btn = e.currentTarget;
485 const form = btn.closest('form');
486 if (!form) return;
487
488 const productId = form.querySelector('input[name="ProductId"]')?.value || "";
489 const variantId = form.querySelector('input[name="VariantId"]')?.value || "";
490 const quantityInput =
491 form.querySelector(`#Quantity_${productId}_${variantId}`) ||
492 form.querySelector('input[name="Quantity"]');
493 const qty = parseInt(quantityInput?.value || "1", 10);
494
495 const unitPriceInclVat = parseFloat("@product.Price.PriceWithVat.ToString(System.Globalization.CultureInfo.InvariantCulture)");
496 const currency = "@Dynamicweb.Ecommerce.Common.Context.Currency.Code";
497 const lineValueInclVat = qty * unitPriceInclVat;
498
499 const msg = document.getElementById(MSG_ID);
500 if (msg) {
501 msg.classList.remove('d-none');
502 setTimeout(() => msg.classList.add('d-none'), 1000);
503 }
504
505 trackAddToCart({ productId, qty, unitPriceInclVat, lineValueInclVat, currency });
506 }
507
508 const btn = document.getElementById(BTN_ID);
509 if (btn) {
510 btn.addEventListener('click', onAddToCartClick, { passive: true });
511 }
512 })();
513 </script>
514
515 <script>
516 (function () {
517 const productId = "@product.Id";
518 const productPriceInclVat = parseFloat("@product.Price.PriceWithVat.ToString(System.Globalization.CultureInfo.InvariantCulture)");
519 const currency = "@Dynamicweb.Ecommerce.Common.Context.Currency.Code";
520
521 if (window.__dwViewContentTracked) return;
522 window.__dwViewContentTracked = true;
523
524 function fireViewContent() {
525 console.log("Meta Pixel - ViewContent", {
526 content_ids: [productId],
527 content_type: 'product',
528 value: productPriceInclVat,
529 currency
530 });
531
532 if (typeof fbq === "function") {
533 fbq('track', 'ViewContent', {
534 content_ids: [productId],
535 content_type: 'product',
536 value: productPriceInclVat,
537 currency
538 });
539 }
540 }
541
542 if (typeof withMarketingConsent === "function") {
543 withMarketingConsent(fireViewContent);
544 } else {
545 fireViewContent();
546 }
547 })();
548 </script>
549
550 @if (!string.IsNullOrEmpty(productIdTag))
551 {
552 <!--$$SnippetStart(meta)-->
553 <meta name="description" content="@metaDescription" />
554 <title>@metaTitle</title>
555 <meta property="og:title" content="@metaTitle">
556
557 <!--$$SnippetEnd(meta)-->
558 }
559