1/* ============================================================= 2 sk-schema.js â AI-Ready JSON-LD 3 svetkouzel.com | Apollo/Classic Å¡ablona na Shoptetu 4 UmÃstÄnà FTP: /user/documents/adminsvet/sk-schema.js 5 Vloženà v zápatà Shoptetu (za script.js od Turského): 6 <script src="https://www.svetkouzel.com/user/documents/adminsvet/sk-schema.js?v=11" defer></script> 7 ============================================================= */ 8 9(function () { 10 'use strict'; 11 12 var SCRIPT_ID = 'sk-product-schema'; 13 var SITE_URL = 'https://www.svetkouzel.com'; 14 var ORG_ID = SITE_URL + '/#organization'; 15 var STORE_ID = SITE_URL + '/#store'; 16 var RETURN_POLICY_ID = SITE_URL + '/#returnPolicy'; 17 18 /* ââ Helpers âââââââââââââââââââââââââââââââââââââââââââââââ */ 19 20 function onReady(fn) { 21 if (document.readyState === 'loading') { 22 document.addEventListener('DOMContentLoaded', fn, { once: true, passive: true }); 23 } else { 24 fn(); 25 } 26 } 27 28 function isProductDetail() { 29 var b = document.body; 30 return b.classList.contains('type-product') && b.classList.contains('type-detail'); 31 } 32 33 function getDL() { 34 try { 35 if (typeof window.getShoptetDataLayer === 'function') { 36 return window.getShoptetDataLayer() || null; 37 } 38 } catch (e) {} 39 return null; 40 } 41 42 function applyGtin(obj, raw) { 43 if (!raw) return; 44 var digits = String(raw).replace(/\D/g, ''); 45 if (!digits) return; 46 var len = digits.length; 47 if (len === 8) obj.gtin8 = digits; 48 else if (len === 12) obj.gtin12 = digits; 49 else if (len === 13) obj.gtin13 = digits; 50 else if (len === 14) obj.gtin14 = digits; 51 else obj.gtin = digits; 52 } 53 54 function getEan() { 55 var el = document.querySelector('.productEan__value') 56 || document.querySelector('[class*="productEan"][class*="value"]') 57 || document.querySelector('[class*="productEan"]'); 58 if (!el) return null; 59 var v = el.textContent.trim(); 60 return /^\d{8,14}$/.test(v) ? v : null; 61 } 62 63 function getRating() { 64 var starEl = document.querySelector( 65 '.p-detail .star[data-original-title], .p-detail-info .star[data-original-title]' 66 ); 67 var ratingValue = null; 68 if (starEl) { 69 var title = starEl.getAttribute('data-original-title') || ''; 70 var m = title.match(/(\d+[.,]\d+|\d+)\s*\/\s*5/); 71 if (m) ratingValue = parseFloat(m[1].replace(',', '.')); 72 } 73 var labelEl = document.querySelector('.p-detail .stars-label, .p-detail-info .stars-label'); 74 var reviewCount = null; 75 if (labelEl) { 76 var mc = labelEl.textContent.match(/(\d+)/); 77 if (mc) reviewCount = parseInt(mc[1], 10); 78 } 79 if (!ratingValue || !reviewCount || reviewCount < 1) return null;
80 if (ratingValue < 0 || ratingValue > 5) return null; 81 return { ratingValue: ratingValue, reviewCount: reviewCount }; 82 } 83 84 function getReviews() { 85 var reviewEls = document.querySelectorAll('[itemprop="review"]'); 86 if (!reviewEls || reviewEls.length === 0) return null; 87 var reviews = []; 88 reviewEls.forEach(function (el) { 89 var ratingEl = el.querySelector('[itemprop="ratingValue"]'); 90 var authorEl = el.querySelector('[itemprop="name"]'); 91 var bodyEl = el.querySelector('[itemprop="reviewBody"]'); 92 var dateEl = el.querySelector('[data-testid="latestContributionDate"]'); 93 var ratingValue = ratingEl ? parseFloat(ratingEl.textContent.trim()) : null; 94 var authorName = authorEl ? authorEl.textContent.trim() : null; 95 var reviewBody = bodyEl ? bodyEl.textContent.replace(/\s+/g, ' ').trim() : null; 96 if (!ratingValue || !authorName) return; 97 if (ratingValue < 1 || ratingValue > 5) return; 98 var review = { 99 '@type': 'Review', 100 'reviewRating': { 101 '@type': 'Rating', 102 'ratingValue': ratingValue, 103 'bestRating': 5, 104 'worstRating': 1 105 }, 106 'author': { '@type': 'Person', 'name': authorName } 107 }; 108 if (reviewBody) review.reviewBody = reviewBody; 109 if (dateEl) { 110 var d = dateEl.textContent.trim().match(/(\d{1,2})\.(\d{1,2})\.(\d{4})/); 111 if (d) review.datePublished = d[3] + '-' + String(d[2]).padStart(2,'0') + '-' + String(d[1]).padStart(2,'0'); 112 } 113 reviews.push(review); 114 }); 115 return reviews.length > 0 ? reviews : null; 116 } 117 118 function getBreadcrumbs() { 119 var items = document.querySelectorAll('[itemtype="https://schema.org/ListItem"]'); 120 if (!items || items.length === 0) return null; 121 var list = []; 122 items.forEach(function (el) { 123 var posEl = el.querySelector('[itemprop="position"]'); 124 var nameEl = el.querySelector('[itemprop="name"]'); 125 var itemEl = el.querySelector('[itemprop="item"]'); 126 var position = posEl ? parseInt(posEl.getAttribute('content') || posEl.textContent) : null; 127 var name = nameEl ? nameEl.getAttribute('data-title') || nameEl.textContent.trim() : null; 128 var url = itemEl ? (itemEl.getAttribute('href') || itemEl.getAttribute('content')) : null; 129 if (!position || !name) return; 130 if (url && url.indexOf('http') !== 0) url = window.location.origin + url; 131 if (!url) url = window.location.href.split('?')[0]; 132 list.push({ 133 '@type': 'ListItem', 134 'position': position, 135 'name': name.replace(/\s+/g, ' ').trim(), 136 'item': url 137 }); 138 }); 139 if (list.length === 0) return null; 140 return { 141 '@context': 'https://schema.org', 142 '@type': 'BreadcrumbList', 143 'itemListElement': list 144 }; 145 } 146 147 function getFaq() { 148 var items = document.querySelectorAll('.js-faq-block .accordion__item, .faq-block .accordion__item'); 149 if (!items || items.length === 0) return null; 150 var faqItems = []; 151 items.forEach(function (item) { 152 var qEl = item.querySelector('.accordion__trigger'); 153 var aEl = item.querySelector('.accordion__content'); 154 if (!qEl || !aEl) return; 155 var question = qEl.textContent.replace(/\s+/g, ' ').trim(); 156 var answer = (aEl.innerText || aEl.textContent).replace(/\s+/g, ' ').trim(); 157 if (!question || !answer) return; 158 faqItems.push({ 159 '@type': 'Question', 160 'name': question, 161 'acceptedAnswer': { '@type': 'Answer', 'text': answer } 162 }); 163 }); 164 if (faqItems.length === 0) return null; 165 return { 166 '@context': 'https://schema.org', 167 '@type': 'FAQPage', 168 'mainEntity': faqItems 169 }; 170 } 171 172 function getDescription() { 173 var el = document.querySelector( 174 '#description .extended-description, #description .basic-description, ' + 175 '#description .description-inner, #description' 176 ); 177 if (!el) return null; 178 var txt = (el.innerText || el.textContent || '').replace(/\s+/g, ' ').trim(); 179 return txt ? txt.slice(0, 5000) : null; 180 } 181 182 function getImage() { 183 var og = document.querySelector('meta[property="og:image"]'); 184 if (og && og.content) return [og.content]; 185 var ip = document.querySelector('meta[itemprop="image"]'); 186 if (ip && ip.content) return [ip.content]; 187 return null; 188 } 189 190 function getAvailability(dlProduct) { 191 if (dlProduct && dlProduct.codes && dlProduct.codes.length > 0) { 192 var code = dlProduct.codes[0]; 193 if (code && code.quantity) { 194 var q = String(code.quantity).toLowerCase(); 195 if (q === '0' || q === 'out of stock') return 'https://schema.org/OutOfStock'; 196 return 'https://schema.org/InStock'; 197 } 198 } 199 var el = document.querySelector('.availability-value, .p-detail-availability, [class*="availability"]'); 200 if (el) { 201 var t = el.textContent.toLowerCase(); 202 if (/nedostup|vyprod|out of stock/.test(t)) return 'https://schema.org/OutOfStock'; 203 if (/objedn\u00E1vce|preorder|p\u0159edobjedn\u00E1vce/.test(t)) return 'https://schema.org/PreOrder'; 204 } 205 return 'https://schema.org/InStock'; 206 } 207 208 function watchParams(callback) { 209 var SKIP = /^(ean|gtin|k\u00F3d|code|sku)$/i; 210 var done = false;
211 function parse() { 212 if (done) return; 213 var tbody = document.querySelector('table.detail-parameters tbody'); 214 if (!tbody) return callback([]); 215 var rows = tbody.querySelectorAll('tr'); 216 if (rows.length === 0) return; 217 done = true; 218 var props = []; 219 rows.forEach(function (row) { 220 if (row.classList.contains('productEan')) return; 221 var th = row.querySelector('th'); 222 var td = row.querySelector('td'); 223 var k = th ? th.textContent.trim() : ''; 224 var v = td ? td.textContent.trim() : ''; 225 if (!k || !v || SKIP.test(k)) return; 226 props.push({ '@type': 'PropertyValue', 'name': k, 'value': v }); 227 }); 228 callback(props); 229 } 230 parse(); 231 if (done) return; 232 var target = document.querySelector('table.detail-parameters'); 233 if (target) { 234 var obs = new MutationObserver(function () { parse(); }); 235 obs.observe(target, { childList: true, subtree: true }); 236 } 237 setTimeout(function () { if (!done) { done = true; callback([]); } }, 3000); 238 } 239 240 /* ââ Organization + WebSite + Store schema âââââââââââââââââ */ 241 242 function buildOrganization() { 243 return { 244 '@context': 'https://schema.org', 245 '@type': ['OnlineStore', 'LocalBusiness'], 246 '@id': ORG_ID, 247 'name': 'Sv\u011Bt Kouzel', 248 'alternateName': 'Svetkouzel.com', 249 'description': 'Specializovan\u00FD obchod s licencovan\u00FDmi Harry Potter produkty \u2013 d\u00E1rky, sladkosti, h\u016Flky a sb\u011Bratelský merch. Kamenn\u00FD showroom v Praze.', 250 'url': SITE_URL, 251 'logo': { 252 '@type': 'ImageObject', 253 'url': 'https://cdn.myshoptet.com/usr/www.svetkouzel.com/user/logos/logo.png', 254 'width': 200, 255 'height': 60 256 }, 257 'image': 'https://cdn.myshoptet.com/usr/www.svetkouzel.com/user/front_images/ogImage/hp.png', 258 'foundingDate': '2022', 259 'legalName': 'FELLICIS s.r.o.', 260 'vatID': 'CZ21058369', 261 'numberOfEmployees': { '@type': 'QuantitativeValue', 'value': 10 }, 262 'priceRange': '150\u20135000 K\u010D', 263 // FakturaÄnà adresa 264 'legalAddress': { 265 '@type': 'PostalAddress', 266 'streetAddress': 'Kytlick\u00E1 759/23', 267 'addressLocality': 'Praha 9', 268 'postalCode': '190 00', 269 'addressCountry': 'CZ' 270 }, 271 // Sklad / provozovna 272 'address': { 273 '@type': 'PostalAddress', 274 'streetAddress': 'Na Pankr\u00E1ci 1352/2', 275 'addressLocality': 'Praha 4', 276 'postalCode': '140 00', 277 'addressCountry': 'CZ' 278 }, 279 'contactPoint': { 280 '@type': 'ContactPoint', 281 'telephone': '+420725338071', 282 'email': '[email protected]', 283 'contactType': 'customer service', 284 'availableLanguage': ['Czech', 'Slovak', 'English'], 285 'hoursAvailable': { 286 '@type': 'OpeningHoursSpecification', 287 'dayOfWeek': ['Monday','Tuesday','Wednesday','Thursday','Friday'], 288 'opens': '09:00', 289 'closes': '17:00' 290 } 291 }, 292 'sameAs': [ 293 'https://www.facebook.com/svetkouzell', 294 'https://www.instagram.com/svetkouzel/' 295 ], 296 'areaServed': ['CZ','SK','HU','DE','AT','PL','HR','SI','DK'], 297 'currenciesAccepted': 'CZK, EUR', 298 'paymentAccepted': 'Credit Card, Bank Transfer, Cash on Delivery', 299 'hasMerchantReturnPolicy': [ 300 { 301 '@type': 'MerchantReturnPolicy', 302 '@id': RETURN_POLICY_ID, 303 'applicableCountry': 'CZ', 304 'returnPolicyCategory': 'https://schema.org/MerchantReturnFiniteReturnWindow', 305 'merchantReturnDays': 14, 306 'returnMethod': 'https://schema.org/ReturnByMail', 307 'returnFees': 'https://schema.org/FreeReturn' 308 }, 309 { 310 '@type': 'MerchantReturnPolicy', 311 'applicableCountry': 'SK', 312 'returnPolicyCategory': 'https://schema.org/MerchantReturnFiniteReturnWindow', 313 'merchantReturnDays': 14, 314 'returnMethod': 'https://schema.org/ReturnByMail', 315 'returnFees': 'https://schema.org/FreeReturn' 316 } 317 ] 318 }; 319 } 320 321 function buildWebSite() { 322 return { 323 '@context': 'https://schema.org', 324 '@type': 'WebSite', 325 '@id': SITE_URL + '/#website', 326 'name': 'Sv\u011Bt Kouzel', 327 'url': SITE_URL, 328 'description': 'Specializovan\u00FD obchod s licencovan\u00FDmi Harry Potter produkty \u2013 d\u00E1rky, sladkosti, h\u016Flky a sb\u011Bratelský merch. Kamenn\u00FD showroom v Praze.', 329 'inLanguage': 'cs-CZ', 330 'publisher': { '@id': ORG_ID }, 331 'potentialAction': { 332 '@type': 'SearchAction', 333 'target': { 334 '@type': 'EntryPoint', 335 'urlTemplate': SITE_URL + '/vyhledavani/?q={search_term_string}' 336 }, 337 'query-input': 'required name=search_term_string' 338 } 339 }; 340 } 341 342 function buildStore() { 343 return { 344 '@context': 'https://schema.org', 345 '@type': 'Store', 346 '@id': STORE_ID, 347 'name': 'Sv\u011Bt Kouzel \u2013 Prodejna Praha', 348 'url': SITE_URL, 349 'telephone': '+420725338071', 350 'email': '[email protected]', 351 'address': { 352 '@type': 'PostalAddress', 353 'streetAddress': 'Na Pankr\u00E1ci 1352/2', 354 'addressLocality': 'Praha 4', 355 'postalCode': '140 00', 356 'addressCountry': 'CZ' 357 }, 358 'geo': { 359 '@type': 'GeoCoordinates', 360 'latitude': 50.0631, 361 'longitude': 14.4289 362 }, 363 'openingHoursSpecification': [ 364 { 365 '@type': 'OpeningHoursSpecification', 366 'dayOfWeek': ['Monday','Tuesday','Thursday','Friday'], 367 'opens': '14:30', 368 'closes': '18:00' 369 }, 370 { 371 '@type': 'OpeningHoursSpecification', 372 'dayOfWeek': ['Saturday','Sunday'], 373 'opens': '15:00', 374 'closes': '18:00' 375 } 376 ], 377 'parentOrganization': { '@id': ORG_ID } 378 }; 379 } 380 381 function injectGlobalSchemas() { 382 // 1. Organization â nahradit existujÃcà chudou verzi od Shoptetu 383 var replaced = false;
384 document.querySelectorAll('script[type="application/ld+json"]').forEach(function (s) { 385 try { 386 var d = JSON.parse(s.textContent); 387 if (d['@type'] === 'Organization' || d['@type'] === 'OnlineStore') { 388 s.textContent = JSON.stringify(buildOrganization()); 389 replaced = true; 390 } 391 } catch (e) {} 392 }); 393 if (!replaced) { 394 var orgScript = document.createElement('script'); 395 orgScript.type = 'application/ld+json'; 396 orgScript.id = 'sk-organization'; 397 orgScript.text = JSON.stringify(buildOrganization()); 398 (document.head || document.documentElement).appendChild(orgScript); 399 } 400 401 // 2. WebSite â pÅidat pokud jeÅ¡tÄ neexistuje 402 var hasWebSite = false; 403 document.querySelectorAll('script[type="application/ld+json"]').forEach(function (s) { 404 try { if (JSON.parse(s.textContent)['@type'] === 'WebSite') hasWebSite = true; } catch (e) {} 405 }); 406 if (!hasWebSite) { 407 var wsScript = document.createElement('script'); 408 wsScript.type = 'application/ld+json'; 409 wsScript.id = 'sk-website'; 410 wsScript.text = JSON.stringify(buildWebSite()); 411 (document.head || document.documentElement).appendChild(wsScript); 412 } 413 414 // 3. Store â pÅidat/aktualizovat (fyzická prodejna â jen CZ web) 415 var existingStore = document.getElementById('sk-local-business'); 416 if (existingStore) existingStore.parentNode.removeChild(existingStore); 417 var storeScript = document.createElement('script'); 418 storeScript.type = 'application/ld+json'; 419 storeScript.id = 'sk-local-business'; 420 storeScript.text = JSON.stringify(buildStore()); 421 (document.head || document.documentElement).appendChild(storeScript); 422 } 423 424 /* ââ Product schema inject âââââââââââââââââââââââââââââââââ */ 425 426 function inject(obj) { 427 var old = document.getElementById(SCRIPT_ID); 428 if (old) old.parentNode.removeChild(old); 429 // Odstranit základnà Product schema od Shoptetu (bez @id) 430 document.querySelectorAll('script[type="application/ld+json"]').forEach(function (s) { 431 if (s.id === SCRIPT_ID) return; 432 try { 433 var d = JSON.parse(s.textContent); 434 if (d['@type'] === 'Product' && !d['@id']) s.parentNode.removeChild(s); 435 } catch (e) {} 436 }); 437 var s = document.createElement('script'); 438 s.type = 'application/ld+json'; 439 s.id = SCRIPT_ID; 440 s.text = JSON.stringify(obj); 441 (document.head || document.documentElement).appendChild(s); 442 } 443 444 /* ââ Hlavnà build funkce âââââââââââââââââââââââââââââââââââ */ 445 446 function tryBuild() { 447 if (!isProductDetail()) return false; 448 449 var dl = getDL(); 450 if (!dl || !dl.product) return false; 451 452 var p = dl.product; 453 var url = (window.location.href || '').split('#')[0]; 454 455 var name = p.name 456 || (document.querySelector('.p-detail .h1, h1') || {}).textContent 457 || null; 458 if (!name) return false; 459 name = name.replace(/\s+/g, ' ').trim(); 460 461 var currency = dl.currency || 'CZK'; 462 var ean = getEan(); 463 var rating = getRating(); 464 var reviews = getReviews(); 465 var images = getImage(); 466 var description = getDescription(); 467 var availability = getAvailability(p); 468 var weightKg = p.weight ? parseFloat(p.weight) : null; 469 var brandName = p.manufacturer || null; 470 var sku = (p.codes && p.codes[0] && p.codes[0].code) ? p.codes[0].code : (p.code || null); 471 var price = (typeof p.priceWithVat === 'number') ? p.priceWithVat : null; 472 var priceUntil = (new Date().getFullYear() + 1) + '-12-31'; 473 474 var category = null; 475 if (p.currentCategory) { 476 var cats = p.currentCategory.split('|'); 477 category = cats[cats.length - 1].trim(); 478 } 479 480 var product = { 481 '@context': 'https://schema.org', 482 '@type': 'Product', 483 '@id': url + '#product', 484 'name': name, 485 'url': url 486 }; 487 488 if (images) product.image = images; 489 if (description) product.description = description; 490 if (sku) product.sku = sku; 491 if (brandName) product.brand = { '@type': 'Brand', 'name': brandName }; 492 if (category) product.category = category; 493 494 applyGtin(product, ean); 495 496 if (weightKg && !isNaN(weightKg) && weightKg > 0) { 497 product.weight = { 498 '@type': 'QuantitativeValue', 499 'value': weightKg, 500 'unitText': 'kg', 501 'unitCode': 'KGM' 502 }; 503 } 504 505 if (rating) { 506 product.aggregateRating = { 507 '@type': 'AggregateRating', 508 'ratingValue': rating.ratingValue, 509 'reviewCount': rating.reviewCount, 510 'bestRating': 5, 511 'worstRating': 1 512 }; 513 } 514 515 if (reviews && reviews.length > 0) product.review = reviews; 516 517 if (price !== null && availability) { 518 product.offers = { 519 '@type': 'Offer', 520 '@id': url + '#offer', 521 'url': url, 522 'price': price, 523 'priceCurrency': currency, 524 'availability': availability, 525 'priceValidUntil': priceUntil, 526 'itemCondition': 'https://schema.org/NewCondition', 527 'seller': { 528 '@type': 'Organization', 529 '@id': ORG_ID, 530 'name': 'Sv\u011Bt Kouzel' 531 }, 532 'hasMerchantReturnPolicy': { '@id': RETURN_POLICY_ID }, 533 'shippingDetails': { 534 '@type': 'OfferShippingDetails', 535 'shippingRate': { 536 '@type': 'MonetaryAmount', 537 'value': '0', 538 'currency': currency 539 }, 540 'shippingDestination': {
541 '@type': 'DefinedRegion', 542 'addressCountry': 'CZ' 543 }, 544 'deliveryTime': { 545 '@type': 'ShippingDeliveryTime', 546 'cutoffTime': '14:00:00+01:00', 547 'handlingTime': { 548 '@type': 'QuantitativeValue', 549 'minValue': 0, 'maxValue': 1, 'unitCode': 'DAY' 550 }, 551 'transitTime': { 552 '@type': 'QuantitativeValue', 553 'minValue': 1, 'maxValue': 3, 'unitCode': 'DAY' 554 } 555 } 556 } 557 }; 558 } 559 560 watchParams(function (additionalProps) { 561 var mapped = { material: null, color: null, extra: [] }; 562 additionalProps.forEach(function (prop) { 563 var k = (prop.name || '').toLowerCase(); 564 if (/^materi\u00E1l$|^material$/.test(k)) { mapped.material = prop.value; } 565 else if (/^barva$|^color$/.test(k)) { mapped.color = prop.value; } 566 else { mapped.extra.push(prop); } 567 }); 568 569 if (mapped.material) product.material = mapped.material; 570 if (mapped.color) product.color = mapped.color; 571 if (mapped.extra.length > 0) product.additionalProperty = mapped.extra; 572 573 inject(product); 574 575 // Breadcrumb 576 var breadcrumb = getBreadcrumbs(); 577 if (breadcrumb) { 578 var oldBC = document.getElementById('sk-breadcrumb'); 579 if (oldBC) oldBC.parentNode.removeChild(oldBC); 580 var bcScript = document.createElement('script'); 581 bcScript.type = 'application/ld+json'; 582 bcScript.id = 'sk-breadcrumb'; 583 bcScript.text = JSON.stringify(breadcrumb); 584 (document.head || document.documentElement).appendChild(bcScript); 585 } 586 587 // FAQ 588 var faq = getFaq(); 589 if (faq) { 590 var oldFaq = document.getElementById('sk-faq'); 591 if (oldFaq) oldFaq.parentNode.removeChild(oldFaq); 592 var faqScript = document.createElement('script'); 593 faqScript.type = 'application/ld+json'; 594 faqScript.id = 'sk-faq'; 595 faqScript.text = JSON.stringify(faq); 596 (document.head || document.documentElement).appendChild(faqScript); 597 } 598 599 // Organization + WebSite + Store i na produktové stránce 600 injectGlobalSchemas(); 601 602 // Debug (aktivujte pÅidánÃm ?schema_debug=1 do URL) 603 if (window.location.search.indexOf('schema_debug=1') !== -1) { 604 console.group('%c\uD83E\uDDD9 Sv\u011Bt Kouzel \u2013 Schema Debug', 'color:#9c27b0;font-size:14px;font-weight:bold'); 605 console.log('Produkt:', name); 606 console.log('EAN:', ean || '\u26A0\uFE0F nenalezen'); 607 console.log('GTIN pole:', ean ? ('gtin' + ean.length) : '\u2014'); 608 console.log('Zna\u010Dka:', brandName || '\u26A0\uFE0F nenalezena'); 609 console.log('Hmotnost:', weightKg ? weightKg + ' kg' : '\u26A0\uFE0F nenalezena'); 610 console.log('Hodnocen\u00ED:', rating ? rating.ratingValue + '/5 (' + rating.reviewCount + 'x)' : '\u26A0\uFE0F nenalezeno'); 611 console.log('Dostupnost:', availability); 612 console.log('Recenze:', reviews ? reviews.length + 'x' : '\u26A0\uFE0F nenalezeny'); 613 console.log('Breadcrumb:', breadcrumb ? breadcrumb.itemListElement.length + ' krok\u016F' : '\u26A0\uFE0F nenalezen'); 614 console.log('FAQ:', faq ? faq.mainEntity.length + ' ot\u00E1zek' : '\u26AA nen\u00ED na t\u00E9to str\u00E1nce'); 615 console.log('Parametry:', additionalProps.length + ' polo\u017Eek'); 616 console.log('Pln\u00E9 schema:', JSON.parse(document.getElementById(SCRIPT_ID).textContent)); 617 console.groupEnd(); 618 } 619 }); 620 621 return true; 622 } 623 624 /* ââ INIT ââââââââââââââââââââââââââââââââââââââââââââââââââ */ 625 626 onReady(function () { 627 setTimeout(function () { 628 629 // Na vÅ¡ech stránkách â Organization + WebSite + Store 630 injectGlobalSchemas(); 631 632 // FAQ a Breadcrumb na ne-produktových stránkách 633 if (!isProductDetail()) { 634 var faq = getFaq(); 635 if (faq) { 636 var oldFaq = document.getElementById('sk-faq');
637 if (oldFaq) oldFaq.parentNode.removeChild(oldFaq); 638 var faqScript = document.createElement('script'); 639 faqScript.type = 'application/ld+json'; 640 faqScript.id = 'sk-faq'; 641 faqScript.text = JSON.stringify(faq); 642 (document.head || document.documentElement).appendChild(faqScript); 643 } 644 645 var breadcrumb = getBreadcrumbs(); 646 if (breadcrumb) { 647 var oldBC = document.getElementById('sk-breadcrumb'); 648 if (oldBC) oldBC.parentNode.removeChild(oldBC); 649 var bcScript = document.createElement('script'); 650 bcScript.type = 'application/ld+json'; 651 bcScript.id = 'sk-breadcrumb'; 652 bcScript.text = JSON.stringify(breadcrumb); 653 (document.head || document.documentElement).appendChild(bcScript); 654 } 655 } 656 657 // Produktová stránka â Product schema 658 if (isProductDetail()) { 659 if (!tryBuild()) { 660 document.addEventListener('ShoptetDataLayerUpdated', function () { 661 if (!document.getElementById(SCRIPT_ID)) tryBuild(); 662 }, { once: true, passive: true }); 663 } 664 } 665 666 }, 500); 667 }); 668 669})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.