Konfigurátor balíčků nemá vlastní šablonu ani routu — vykresluje se do obsahu běžné stránky e-shopu. Nasazení je proto instalatérská práce: nahrát dva soubory, zaregistrovat je v administraci, vložit shortcode do stránky a ověřit, že vše sedí. Tenhle návod je psaný pro vývojáře nebo agenturu, která e-shop spravuje.
Ve všech ukázkách používáme smyšlený e-shop www.example.cz s projectId 123456 a konfiguraci Kávový balíček se shortcodem [w-multipack-ABC12].
Pokud ještě nevíte, co doplněk dělá a jak vzniká sada, začněte návodem Jak funguje doplněk Sestav si vlastní balíček.
Co potřebujete, než začnete
| Co | Poznámka |
|---|---|
| Shoptet Premium | doplněk pracuje se Shoptet API a s nativním košíkovým rozhraním šablony |
| Aktivní licence doplňku | po instalaci doběhne úloha, která v e-shopu připraví skrytou kategorii pro generované sady |
| Přístup do administrace balíčků | webová administrace na naší straně, kde se zakládají konfigurace |
| Shortcode konfigurace | vygeneruje se při jejím založení, v administraci se zobrazuje v hranatých závorkách |
| Testovací konfiguraci | vyžádejte si ji u nás — zakládání sad vytváří v e-shopu reálné produkty, takže se netestuje na ostré konfiguraci |
| FTP nebo souborový manažer Shoptetu | pro nahrání JS a CSS |
Co naopak nepotřebujete: API klíč, token ani podpis požadavku. Veřejné endpointy doplňku jsou neautentizované a e-shop se identifikuje číslem projectId v adrese.
Krok 1: Nahrání JS a CSS na Shoptet FTP
Shoptet má vlastní úložiště statických souborů dostupné přes FTP; obsah se servíruje z domény e-shopu pod cestou /user/documents/. Doporučujeme vlastní podadresář:
/user/documents/multipack/
├── multipack.js
├── multipack.css
└── img/placeholder.svg
Výsledné veřejné adresy pak vypadají takto:
https://www.example.cz/user/documents/multipack/multipack.js
https://www.example.cz/user/documents/multipack/multipack.css
Podadresář používejte vždycky. Kořen /user/documents/ bývá na starších e-shopech skládka po předchozích dodavatelích a přepsat tam cizí soubor je otázka jednoho nepozorného přetažení.
Počítejte s tím, že jde o čistě statické úložiště — žádné PHP, žádné přepisování cest. Nahrání se navíc neprojeví okamžitě, protože soubory jdou přes CDN vrstvu s dlouhým TTL; proto cache busting v dalším kroku. FTP taky nemá verzování ani rollback, takže si zdrojáky držte v gitu a na FTP je jen deployujte. Alternativou je hostovat assety na vlastní CDN — dává to smysl, když máte build pipeline nebo spravujete stejný doplněk na víc e-shopech.
Krok 2: Registrace v HTML vložkách
Shoptet umí vložit vlastní HTML do hlavičky a do patičky každé stránky e-shopu. V administraci to najdete pod vzhledem e-shopu jako HTML vložky / HTML kód (název položky se mezi verzemi liší) — jsou tam dvě pole: jedno se vkládá před </head>, druhé před </body>.
Do hlavičky patří CSS:
<!-- Sestav si vlastní balíček – konfigurátor -->
<link rel="stylesheet" href="/user/documents/multipack/multipack.css?v=1.00">
Do patičky skript:
<!-- Sestav si vlastní balíček – konfigurátor -->
<script src="/user/documents/multipack/multipack.js?v=1.00" defer></script>
Používejte relativní cesty, ne absolutní s doménou. E-shop může běžet na víc doménách (jazykové mutace, testovací doména na myshoptet.com) a absolutní adresa by je rozbila.
Proč defer i v patičce
Atribut defer zajistí, že se skript stáhne paralelně s parsováním dokumentu a spustí se až po jeho dokončení. Tím pádem neblokuje vykreslování (což se pozná na LCP) a zároveň má k dispozici hotový DOM i objekty Shoptetu. Uvnitř skriptu se přesto navažte na DOMContentLoaded, aby kód přežil i to, že by někdo defer odstranil nebo vložku přesunul.
Proč ?v= na konci adresy
Soubory z /user/documents/ jdou přes CDN a browser cache s dlouhým TTL. Bez změny adresy se nová verze nemusí projevit hodiny a klient bude oprávněně tvrdit, že jste nic nenasadili. Řešení je triviální: při každé změně souboru zvyšte číslo verze v HTML vložce.
Tři věci, které se vyplatí dodržet:
- Verzujte JS a CSS společně jedním číslem. Rozjeté verze (CSS
1.02, JS1.07) jsou klasický zdroj hlášek typu „u mě to vypadá jinak". - Ideálně použijte hash obsahu generovaný buildem místo ručně psaného čísla.
- Pamatujte, že deploy je vždy dvoukrokový — nahrát soubor a upravit vložku. Když zapomenete na druhý krok, nestane se vůbec nic, a to je ta nejhorší varianta.
Ještě jedna věc: HTML vložky se aplikují na všechny stránky e-shopu, včetně košíku a objednávky. Skript proto musí sám poznat, jestli má na dané stránce co dělat — typicky se ptá „je v obsahu shortcode?" — a jinak se okamžitě ukončit. Žádná těžká práce ani volání API „pro jistotu" na každém zobrazení stránky.
Krok 3: Stránka se shortcodem
- V administraci Shoptetu založte novou stránku, například
/kavovy-balicek/. - Do editoru napište shortcode jako prostý text:
[w-multipack-ABC12]. - Kolem něj si napište libovolný marketingový obsah — nadpis, odrážky s výhodami, badge se slevou, fotky. Nahradí se jen samotný shortcode, zbytek stránky zůstane.
- Uložte a otevřete stránku na frontendu.
Shortcode přitom nemusí být jen na statické stránce. Funguje všude, kde se renderuje uživatelský obsah — v článku blogu, v popisu kategorie, v textovém bloku na homepage. Z toho plyne důležité pravidlo pro váš skript: podmínkou spuštění ať je přítomnost shortcodu, ne typ stránky. Statické stránky mají v dataLayeru jiný pageType než kategorie nebo homepage a navázání na něj vás dřív nebo později zradí.
Při hledání shortcodu nahrazujte konkrétní textový uzel, ne innerHTML celého kontejneru obsahu. Přepis innerHTML sice funguje, ale zabije event listenery všeho uvnitř — jiných doplňků i nativních komponent šablony.
Krok 4: Kontext ze Shoptet dataLayeru
Doplněk nemá vlastní konfigurační objekt. Vše potřebné je ve standardním dataLayeru Shoptetu, což je oficiální a stabilní rozhraní: projectId do adresy API, currency pro výběr správné cenové hodnoty, currencyInfo pro formátování a customer.priceListId pro ceny podle cenové hladiny přihlášeného zákazníka.
function getShoptetContext() {
if (typeof getShoptetDataLayer === 'function') {
const data = getShoptetDataLayer();
if (data) return data;
}
if (Array.isArray(window.dataLayer)) {
const entry = window.dataLayer.find(
(item) => item && item.shoptet && item.shoptet.projectId !== undefined
);
if (entry) return entry.shoptet;
}
return {};
}
const ctx = getShoptetContext();
const projectId = ctx.projectId; // 123456
const currency = ctx.currency || 'CZK'; // "CZK"
const priceKey = 'price_' + currency; // "price_CZK"
const rawPriceList = ctx.customer && ctx.customer.priceListId;
const priceListId = Number.isInteger(rawPriceList) ? rawPriceList : null;
if (!projectId) return; // dataLayer nedorazil, nemá smysl volat API
Kód je obranný schválně. Oficiální helper getShoptetDataLayer() nemusí být v každé verzi šablony k dispozici, proto ten fallback na syrové pole. A priceListId může chybět nebo být null — pak se poslední segment adresy prostě vynechá. Právě tady vzniká nejčastější chyba celé integrace: zápis ${priceListId ?? null} vložený rovnou do šablonového řetězce vyrobí v adrese literál /null, konfigurace se nenačte a na stránce zůstane viditelný holý shortcode.
Formátování cen berte také z dataLayeru (symbol, symbolLeft, decimalSeparator, thousandSeparator, priceDecimalPlaces), ne natvrdo. Jinak bude widget psát 779,45 Kč na e-shopu, který všude jinde ukazuje 779 Kč. Zákazník si toho nevšimne, klient na první schůzce ano.
Krok 5: Vložení do košíku
Backend vrátí kód nově vytvořené sady (v našem příkladu WT-SET-00042). Ten předejte nativní funkci Shoptetu:
function addSetToCart(code, amount) {
const ok = typeof shoptet !== 'undefined'
&& shoptet.cartShared
&& typeof shoptet.cartShared.addToCart === 'function';
if (!ok) {
showError('Košík se nepodařilo otevřít, zkuste stránku načíst znovu.');
return false;
}
shoptet.cartShared.addToCart({ productCode: code, amount: amount });
return true;
}
Vlastní fetch na košíkový endpoint Shoptetu vypadá jako kratší cesta, ale nefunguje spolehlivě a nefunguje dobře. Důvody jsou čtyři:
- CSRF ochrana. Košíkové akce Shoptetu chrání rotující token, který nativní funkce dodá za vás.
- Přepočet košíku. Po přidání se aktualizuje mezisoučet, doprava zdarma, dárky, slevové mechaniky i ikona košíku v hlavičce. Vlastní požadavek tohle neudělá a zákazník uvidí nesouhlasící čísla.
- Zpětná vazba pro zákazníka. Šablona zobrazí své standardní potvrzení, které zákazník zná ze zbytku e-shopu — a vy nemusíte nic stavět.
- Odolnost. Interní košíkové endpointy se mohou změnit,
shoptet.cartSharedje součást veřejného šablonového API.
Pokud potřebujete na přidání zareagovat (zavřít konfigurátor, odeslat událost do GA4), poslouchejte DOM události Shoptetu, například ShoptetDOMCartContentLoaded.
Ověřovací checklist po nasazení
Vše kontrolujte v DevTools a na testovací konfiguraci:
- Assety:
multipack.cssimultipack.jsvrací 200, adresa obsahuje aktuální?v=, skript se načítá právě jednou. - Mount: na stránce není vidět holý text
[w-multipack-ABC12], zbytek obsahu stránky zůstal nedotčený, konzole je čistá. - Konfigurace: právě jeden požadavek na konfiguraci se stavem 200, adresa neobsahuje
/nullani/undefined, počet slotů odpovídá hodnotěproduct_count. - Výběr: během skládání balíčku neproběhne žádný síťový požadavek, orientační cena sedí (289 + 329 + 299 = 917 Kč, po 15 % → 779,45 Kč), tlačítko do košíku je nedostupné, dokud není obsazený každý slot.
- Košík: po kliknutí odejde požadavek na založení sady, zobrazená závazná cena je ta z odpovědi, položka je v košíku a ikona košíku se aktualizovala. Rychlý dvojklik nesmí vytvořit dvě položky.
- Napříč: mobilní zařízení, pomalé připojení (musí být vidět stav načítání, ne prázdno), přepnutí měny, přihlášený zákazník s cenovou hladinou.
- Objednávka: jednu testovací objednávku dokončete a zkontrolujte, že se sada správně propsala.
Když to nefunguje
- Konfigurátor se nevykreslí vůbec. Zkontrolujte v Network, jestli se
multipack.jsnačetl. Stav 404 znamená překlep v cestě, žádný požadavek znamená neuloženou HTML vložku — nebo vložku uloženou u jiné jazykové mutace. - Na stránce zůstal viditelný shortcode. Nejčastěji ho rozbil WYSIWYG editor. Otevřete zdrojový kód stránky a najděte
w-multipack: uvidíte tam entity místo hranatých závorek, uvnitř nebo text rozsekaný do několika elementů po vložení z Wordu. Spolehlivý postup je přepnout editor do režimu zdrojového kódu a napsat shortcode ručně na samostatný řádek. Pozor, shortcode je case-sensitive — pět znaků za prefixem jsou vždy velká písmena a číslice. - Konfigurace se nenačte. Zkontrolujte adresu požadavku: nesmí obsahovat
/null(viz krok 4) a shortcode v ní musí být bez hranatých závorek. Odpověď 404 znamená, že dvojiceprojectIda shortcode neodpovídá žádné konfiguraci — typicky testujete na jiném e-shopu, než kde je založená. - Nejde vložit do košíku. Pokud
shoptet.cartSharednení definovaný, běží váš skript dřív než skripty šablony — zkontrolujtedefera to, že jste v patičce, ne v hlavičce. - Konflikt se šablonou. Konfigurátor přestal fungovat po přidání jiného doplňku? Podezřelý číslo jedna je cizí skript, který přepisuje
innerHTMLkontejneru obsahu. Své CSS mějte zanořené pod kořenovou třídou widgetu, ať nestylujete holé selektory na celém e-shopu, a init si pojistěte globálním příznakem pro případ, že by se skript načetl ze dvou vložek.
Podrobnější rozpad symptomů, příčin a řešení je ve FAQ dokumentu na GitHubu.
Kam dál
- API doplňku pro vývojáře — kontrakt obou endpointů a minimální implementace.
- Starter widget na GitHubu — funkční vanilla JS implementace včetně HTML vložek k převzetí. Celý repozitář najdete na github.com/Webotvurci-s-r-o/shoptet-premium-multipack.
- Sestav si vlastní balíček — produktová stránka doplňku.
Potřebujete testovací konfiguraci nebo se někde zaseklo nasazení? Napište na jsme@webotvurci.cz.