Server-Side Google Tag Manager šablona pro odesílání konverzních událostí do Seznam SEM API (https://sem.seznam.cz/rtgconv).
Data události a uživatele zadáváte v tabulkách Klíč – Hodnota (klíč vybíráte ze seznamu, hodnotu přiřadíte z GTM proměnné) nebo jako objekt z GTM proměnné. Volitelně umí šablona část dat předvyplnit z příchozí GA4 události (getAllEventData()); ve výchozím stavu je to vypnuté.
Změny mezi verzemi a kontrolní postup po aktualizaci (upgrade notes, Preview checklist) jsou v CHANGELOG.md. Přechod z verze 2.x popisuje sekce Přechod na verzi 3. Problémy, které Seznam v S2S datech vidí nejčastěji (pokrytí sid, hity před souhlasem, quantity 0, null/undefined, Purchase bez order_id, „denied“ po přijetí cookie lišty), shrnuje sekce Nejčastější problémy v datech.
Serverová šablona nenahrazuje frontendový skript sul.js. Ten je stále potřeba, protože na webu vytváří identifikátory sid a udid, které Seznam používá pro párování uživatele.
Doporučený postup:
- Na webu načtěte oficiální Seznam skript
sul.jsnebo použijte frontendovou GTM šablonu. - Hodnoty
sidaudiddostaňte do serverové šablony jedním ze dvou způsobů:- Předáním jako GTM proměnné (řádky
sidaudidv tabulce User data), nebo - Automaticky z request cookies — od verze 2.3 šablona umí jako fallback přečíst
sidaudidz příchozích cookies (sid,udid). Viz Auto-map sid/udid z cookies.
- Předáním jako GTM proměnné (řádky
sid a udid se neposílají zahashované. Jsou to hodnoty ze sul.js.
sid vzniká až po udělení souhlasu a po asynchronním požadavku sul.js na identitu. Načtěte sul.js na každé stránce před GA4 tagem; událost odeslaná dřív sid neobsahuje.
sul.js ukládá cookies sid a udid na doménu tvořenou posledními dvěma částmi hostname webu: z www.eshop.cz vznikne .eshop.cz. Prohlížeč tyto cookies posílá jen na adresy pod touto doménou. SGTM endpoint proto musí běžet na subdoméně stejné domény, například sgtm.eshop.cz. Na endpoint s jinou doménou (výchozí adresa Cloud Run, doména poskytovatele hostingu) cookies sid a udid nedorazí a cookie fallback nic nedoplní.
1. CMP → sul.js. Pokud CMP nepoužívá IAB TCF, předejte její stav také knihovně Seznamu: po načtení sul.js zavolejte SEM('updateConsent', {consent_mode: stavZCMP}) při inicializaci stránky (výchozí stav CMP) a po každé změně volby uživatele. Samotný Google Consent Mode update tento krok nenahrazuje. Bez tohoto propojení sul.js cookies sid ani udid nevytvoří (ověřeno v testovacím kontejneru 26. 10. 2026: po zavolání vznikly do 6 s).
Příklad. Funkce nactiStavCmp() a priZmeneCmp() nahraďte API vaší CMP a kategorie (marketing, analytics, functional) kategoriemi, které vaše CMP používá. Hodnoty musí odpovídat skutečné volbě uživatele, ne napevno granted. Funkce semState() vrátí granted jen pro true, 1, '1', 'true' a 'granted'; cokoli jiného (false, 'denied', 'false', '0', neznámá hodnota) je denied. Používá-li vaše CMP jiné hodnoty souhlasu (například 'accepted'), doplňte je do semState() výslovně.
<script src="https://l.seznam.cz/sul.js?id=VASE_SEM_ID"></script>
<script>
function semState(v) {
return (v === true || v === 1 || v === '1' || v === 'true' || v === 'granted') ? 'granted' : 'denied';
}
function semConsentMode(stav) {
return {
ad_storage: semState(stav.marketing),
ad_user_data: semState(stav.marketing),
ad_personalization: semState(stav.marketing),
analytics_storage: semState(stav.analytics),
functionality_storage: semState(stav.functional)
};
}
if (typeof window.SEM === 'function') {
// Při inicializaci stránky: aktuální (výchozí) stav CMP.
SEM('updateConsent', { consent_mode: semConsentMode(nactiStavCmp()) });
// Po každé změně volby uživatele.
priZmeneCmp(function (stav) {
SEM('updateConsent', { consent_mode: semConsentMode(stav) });
});
}
</script>2. CMP → serverový tag. Proměnnou se stavem souhlasu namapujte do Consent Mode Object v každém SEM tagu, včetně tagů se zapnutým GA4 prefill. GA4 prefill consent neodvozuje; bez tohoto pole odejde hit bez informace o souhlasu (warning no consent signal). Propojení CMP → sul.js a přenos CMP → serverový tag jsou dva samostatné kroky; ověřte oba. Jak stav souhlasu do SGTM přenést, popisuje sekce Přenos stavu souhlasu do SGTM.
3. Hity těsně po udělení souhlasu. Automaticky znovu odeslaný page_view po kliknutí na „Přijmout“ SEM tag nespustí. Postup popisuje sekce Hity před souhlasem a po něm.
Pole S2S SEM ID (Sklik) je identifikátor pro server-to-server měření. Najdete ho ve Skliku v pokročilém nastavení účtu. Není to stejné ID jako frontendové sul.js?id=....
Šablona kontroluje, že S2S SEM ID má přesně 24 znaků z 0-9 a a-z (^[0-9a-z]{24}$), jak vyžaduje schéma. Jiná hodnota tag zastaví a nic se neodešle. Od verze 3 platí kontrola vždy; dřívější volba Strict Event Validation se ignoruje.
Frontendové i S2S SEM ID mají 24 znaků, takže jejich záměnu lokální kontrola nerozpozná. Podle dokumentace Seznamu může odpověď 401/403 znamenat chybné SEM ID nebo nepřístupný endpoint; šablona k takové odpovědi zaloguje nápovědu.
Email, telefon, jméno, příjmení, adresa a další PII pole musí být zahashovaná pomocí SHA-256 už před odesláním do SGTM. Serverová šablona hodnoty pouze předává dál.
Výjimky:
sidaudidse nehashují.subscription_idse posílá tak, jak ho máte v systému.review_emailpro Zboží.cz dotazník spokojenosti se posílá jako plain text.
Seznam v S2S datech opakovaně vidí šest problémů. Část z nich řeší šablona, zbytek je potřeba opravit na webu nebo v kontejneru. Opravy v šabloně platí od verze 2.3.1; starší verze odesílaly quantity 0, hodnoty null, texty 'undefined' / 'null' a GA4 Purchase s order_id: null. Verzi, která hit poslala, uvádí api.template_version v payloadu a hlavička X-Client-Version (verze 2.3.0 hlásí 2.2.1).
| Problém | Co dělá šablona (od 2.3.1) | Co nastavit na webu a v kontejneru |
|---|---|---|
Nízké pokrytí sid |
Doplní sid/udid z cookies, kontroluje jejich tvar, bez platného sid zaloguje warning. sid vytvořit neumí. |
sul.js před GA4, SEM('updateConsent', …), SGTM na stejné doméně jako web. |
| Hity před souhlasem | Hity podle souhlasu neblokuje; předá stav souhlasu, který dostane. | Consent Mode Object v každém tagu, CMP před GTM, pomocná událost po souhlasu. |
quantity 0 |
Položku s neplatným množstvím zahodí, chybějící množství odešle jako 1. |
Celé quantity alespoň 1 v datech webu. |
Hodnoty null a undefined |
Nevyplněné hodnoty a texty 'undefined' / 'null' neodešle; neplatné nepovinné hodnoty vynechá. |
Opravit GTM proměnné, které warning jmenuje. |
Purchase bez order_id |
Purchase bez order_id, currency nebo value neodešle; tag skončí Failed. |
transaction_id přímo na události purchase, nebo řádek order_id v tabulce Event data. |
| „denied“ i po přijetí cookie lišty | Převede 1, '1' a 'true' na granted; chybný consent tag zastaví. |
Projít příčiny níže v sGTM Preview. |
S BigQuery loggingem změříte dotazem Dotaz na kvalitu dat pokrytí sid a udid, neplatné quantity, hodnoty null a undefined, Purchase bez order_id (jen u verzí před 2.3.1) a hity bez consent_mode nebo s ad_storage denied. Zda hit odešel před souhlasem, nebo s „denied“ po přijetí cookie lišty, z payloadu nepoznáte; to ověříte v sGTM Preview.
sid vytváří na webu sul.js, a to až po udělení souhlasu a po asynchronním požadavku na identitu. Serverová šablona sid nevytváří: převezme ho z tagu, nebo z cookie sid v requestu.
Příčiny:
sul.jsna stránce chybí nebo se načte až po GA4 tagu; událost odeslaná dřív odejde bezsid, pokud ještě není k dispozici platná identita (sul.jsje stále potřeba).- CMP bez IAB TCF nepředá souhlas
sul.jsvolánímSEM('updateConsent', …). Bez nějsul.jscookiessidaniudidnevytvoří (Souhlas musí dostatsul.jsi serverový tag). - SGTM běží na jiné doméně než web, takže cookies
sidaudiddo SGTM nedorazí (SGTM endpoint musí být na stejném webu). - Vstupní stránka:
page_viewodejde bezsid, pokud ještě není k dispozici platná identita. Existující platnésidšablona předá i přidenied; omezený automatický redispatch v GA4 Advanced Consent Mode popisuje bod 2. - Safari (ITP) maže cookies
sidaudidpo 7 dnech bez interakce s webem (Auto-map sid/udid z cookies). - Namapovaný
sidv jiném tvaru nežid=…|t=…|te=…|c=<32 znaků>šablona zahodí (warningignoring malformed sid from the tag configuration) a použije cookiesid, pokud je cookie fallback zapnutý a cookie má správný tvar.
Kontrola v sGTM Preview: hit bez platného sid zaloguje warning no valid sid. Diagnostický řádek Request (Console logging always, nebo debug v Preview) uvádí v poli Identity zdroj sid a udid: tag, cookie nebo missing.
Šablona hity podle souhlasu neblokuje. Odešle každý hit, na který se tag spustí, se stavem souhlasu z polí Consent Mode Object a Consent String. Hit před souhlasem tedy nese výchozí stav CMP; jak ho vyhodnotí, je na Seznamu (Co šablona s consentem dělá a co ne). Kdy se tag spouští, určuje jeho trigger v SGTM.
Co zkontrolovat:
- Consent Mode Object je namapovaný v každém SEM tagu, včetně tagů s GA4 prefill. Bez něj hit odejde bez
consent_mode. Když není vyplněný ani Consent String, šablona zaloguje warningno consent signala hit nenese žádnou informaci o souhlasu (Přenos stavu souhlasu do SGTM). - CMP se načítá před GTM a nastavuje výchozí stav (
default), aktualizaci (update) await_for_update. - V testovaném GA4 Advanced Consent Mode toku 26. 10. 2026 se po udělení
ad_storageznovu odeslal tentýžpage_viewsx-ga-gcu; SEM tag se na tomto omezeném redispatchi nespustil, zatímco nový běžnýpage_viewpo souhlasu ho spustil. U vlastního webu ověřte původní hit, redispatch a seznam spuštěných tagů v Preview. Postup s pomocnou událostísem_consent_readypopisuje sekce Hity před souhlasem a po něm.
Před verzí 2.3.1 šablona množství z GA4 položek zaokrouhlovala dolů (0.5 → 0) a množství z ostatních zdrojů nekontrolovala. Od verze 2.3.1 platí pro contents ze všech zdrojů:
- Chybějící
quantityse odešle jako1. - Položka s množstvím 0, záporným, desetinným nebo nečíselným se zahodí s warningem
…quantity: expected integer >= 1, got …; dropping the item. Ostatní položky i událost se odešlou. - Když se zahodí všechny položky,
contentsse neodešle.
Oprava je v datech webu: posílejte quantity jako celé číslo alespoň 1. Pravidla popisuje sekce Contents - ruční formát.
Zdrojem bývá GTM proměnná, která na dané události nemá hodnotu, nebo se vyhodnotí na text 'undefined' / 'null'. Před verzí 2.3.1 šablona takový text odeslala a přepsala jím platnou hodnotu z nižší vrstvy, NaN a Infinity odeslala jako null a klíče mimo schéma Seznamu přeposílala. Od verze 2.3.1:
undefined,null, prázdný řetězec a text'undefined'/'null'znamenají nevyplněnou hodnotu: nic nepřepíšou a neodešlou se. Text zaloguje warning<pole> is the placeholder string "undefined"; treating it as missing(u textu'null'je v řádku"null"). Výjimkou jsou volné textysearch_string,content_nameacontent_category, kde text zůstane.- Neplatná nepovinná hodnota (například číslo
1 234,50) se vynechá s warningem; NaN ani Infinity se neodešlou. - Klíč mimo schéma Seznamu se neodešle (warning
… is not a Seznam field, dropping).
Oprava: opravte mapování proměnné, kterou warning jmenuje. Pravidla popisuje sekce Typová normalizace.
Před verzí 2.3.1 šablona kontrolovala vstupní pole místo odesílaného payloadu, takže GA4 Purchase mohl odejít s order_id: null, a GA4 prefill převáděl objekt v transaction_id na text "[object Object]". Od verze 2.3.1 se kontroluje výsledný payload: Purchase bez order_id, currency nebo value tag zastaví (Failed), nic neodešle a zaloguje Seznam SEM [ERROR]: Purchase requires: <chybějící pole>. Seznam tedy Purchase bez order_id nedostane; chybu uvidíte jako neúspěšný tag v sGTM.
order_id šablona bere z těchto vrstev, pozdější přepisuje dřívější: GA4 prefill (transaction_id → id → orderNo), Event Data Object, starší pole Order ID, starší tabulka Event Data Overrides (v2.x), tabulka Event data (řádek order_id).
Co zkontrolovat:
- S GA4 prefill musí být
transaction_idv event datech samotné událostipurchase. Šablona čte jen data události, na kterou se spustila. valueje hodnota bez DPH v CZK; šablona ji nedopočítává z položek.- Verze 2.3.0 a 2.3.1: tag vytvořený ve verzi 2.2.x nebo starší s vyplněnými jednotlivými poli nemá uložený režim vstupu a GTM mu jednotlivá pole nepředá. Purchase pak skončí chybou
Purchase requires: …, pokudorder_id,currencyavaluenedodá GA4 Auto-Map; ve verzi 2.3.1 je může dodat i jiná doručená vrstva, například Advanced Overrides. Ve verzi 2.3.1 zvolte v Event Data input mode a User Data input mode režim, ve kterém má tag hodnoty (Individual fields pro jednotlivá pole, Object variable pro Event/User Data Object), a tag uložte. Jeden režim skryje pole druhého: používá-li tag obojí, přidejte potřebné klíče z druhého režimu jako řádky Event Data Overrides / User Data Overrides (skupina Advanced Overrides, platí v obou režimech), nebo aktualizujte na verzi 3 (Výjimky).
Šablona stav souhlasu nevytváří. Odešle to, co dostane v polích Consent Mode Object a Consent String; od verze 2.3.1 převede 1, '1' a 'true' na granted a 0, '0' a 'false' na denied. Příčiny, které lze ověřit v sGTM Preview:
- Hit z doby před souhlasem. Hit odeslaný před aktualizací souhlasu nese výchozí stav a automaticky znovu odeslaný hit po přijetí SEM tag nespustí (bod 2).
- Chybějící nebo chybné mapování. Chybí-li Consent Mode Object i Consent String, platný hit odejde bez consentu s warningem
no consent signal. Obsahuje-li vyplněný Consent Mode Object obal{"consent_mode": {...}}nebo zkrácený JSON, od verze 2.3.1 tag skončí Failed s řádkemSeznam SEM [ERROR]: consentModeObject: …. - Částečný souhlas. CMP udělí jen část souhlasů a
ad_user_dataneboad_personalizationzůstanedenied. Hodnoty proměnné musí vycházet ze skutečné volby uživatele v CMP. - TCF string má přednost. Vyplněný Consent String (IAB TCF) Seznam vyhodnocuje přednostně před
consent_mode. Pole vyplňte jen tehdy, když CMP je IAB TCF v2 a má Seznam ve vendor listu (IAB TCF consent string). - Starší verze šablony. Před verzí 2.3.1 šablona převáděla na
granted/deniedjentrue/false; hodnoty jako1,'1'nebo'true'odeslala beze změny, mimo hodnoty schématu (granted,denied).
Ověření: v diagnostickém řádku Request porovnejte Consent.x_ga_gcs (stav Google Consent Mode, který viděl GA4; G111 znamená ad_storage i analytics_storage granted) s klíči ad_storage a analytics_storage v Consent.consent_mode. x_ga_gcs nepopisuje ostatní tři podporované klíče a chybí, když event data hodnotu x-ga-gcs neobsahují (například událost z jiného klienta než GA4). Když se klíč přítomný v obou liší, proměnná se stavem souhlasu neodpovídá stavu Google Consent Mode; zdroj proměnné ověřte proti CMP pro daný hit. Částečný consent_mode sám o sobě chyba není. Stav souhlasu pro sul.js na webu nastavuje samostatný krok (SEM('updateConsent', …) u CMP bez IAB TCF); ověřte oba.
- Otevřete Server-Side GTM container.
Templates->Tag Templates->New-> menu (...) ->Import.- Vyberte soubor
template.tpl. - Zkontrolujte nová oprávnění a šablonu uložte.
Oprávnění šablony (kromě logging, read_request a access_bigquery):
read_event_data- čtení příchozích event dat pro GA4 prefill, název události z GA4,sznaiidz URL a IP/User-Agent.set_cookies- zápis cookiesznaiid.get_cookies- čtení cookiessznaiid,sid,udid.read_container_data- zjištění, zda kontejner běží v Preview nebo debug režimu (Console loggingdebug). Nové ve verzi 3.send_http- od verze 3 jen nahttps://sem.seznam.cz/rtgconv(dřívehttps://sem.seznam.cz/*).
Při aktualizaci na verzi 3 zkontrolujte na záložce Permissions nové read_container_data a užší send_http.
Na tuto sekci odkazuje řádek Seznam SEM [WARN]: v2.x settings in use: … (README "Přechod na verzi 3"). Všechny změny i s tím, co zkontrolovat, jsou v CHANGELOG.md (3.0.0, Upgrade notes).
Verze 3 zjednodušuje rozhraní. U Event data a User data najdete jeden objekt z GTM proměnné a jednu tabulku Klíč – Hodnota, kde klíč vybíráte ze seznamu. Nový tag má 21 polí a 4 pole pro BigQuery logging. Volby User Data input mode a Event Data input mode zmizely. Volby neurčovaly skládání payloadu v JavaScriptu; oprava G5 ve verzi 2.3.1 čte Event Data input mode jen kvůli chybové nápovědě. GTM však šabloně nepředával hodnoty polí, která tyto volby skrývaly; ve verzi 3 se tato pole znovu použijí (viz výjimky níže).
Nastavení z verze 2.x se při aktualizaci zachovají, s výjimkami uvedenými níže. Dřívější jednotlivá pole, tabulky Overrides a dřívější nastavení najdete ve sbalené skupině Starší pole (v2.x). Šablona je dál používá. Když tag některé z nich používá, zapíše při každém spuštění do logu jeden řádek:
Seznam SEM [WARN]: v2.x settings in use: userEmail��user_data.em, orderId→event_data.order_id, alias email→em, ga4.orderNo, testMode; move them to the v3 tables/settings (README "Přechod na verzi 3") | trace=…
Řádek obsahuje jen názvy, nikdy hodnoty. Loguje se vždy, nezávisle na nastavení Console logging, i když tag skončí chybou. Starší pole ve verzi 3 fungují. Pozdější verze je buď zachová, nebo hit s vyplněným starším polem zastaví s jasným řádkem [ERROR]; takovou změnu předem oznámíme v CHANGELOGu.
- Nejdřív aktualizujte na 2.3.1 a opravte všechny
[ERROR]a[WARN]. - Aktualizujte na verzi 3. Na záložce Permissions zkontrolujte nové oprávnění
read_container_dataa užšísend_http(jenhttps://sem.seznam.cz/rtgconv). - V Preview si přečtěte řádek
v2.x settings in use. - Pro každou položku přidejte řádek do nové tabulky podle převodní tabulky níže. Pak starší pole vymažte: text smažte, Include status odškrtněte, řádky starých Overrides odstraňte.
- Test Mode: v nastavení Console logging zvolte úroveň a Test Mode odškrtněte. Dokud je zaškrtnutý, loguje se v režimu
always. - Znovu otestujte v Preview. Řádek
v2.x settings in usezmizí, jakmile tag žádné starší pole nepoužívá. Pak publikujte.
| Dřívější pole | Nový řádek tabulky |
|---|---|
| SID / UDID | sid / udid (User data) |
| Email, Phone, First Name, Last Name | em, ph, fn, ln |
| Gender, Date of Birth, City, Region, Postal Code, Street, Country, Subscription ID | ge, db, ct, region, zp, sr, country, subscription_id |
| Order ID, Currency, Value, Value Tax | order_id, currency, value, value_tax (Event data) |
| Content Type, Contents, Product IDs | content_type, contents, product_ids |
| Delivery Price, Delivery Type, Payment Type, Other Costs | delivery_price, delivery_type, payment_type, other_costs |
| Predicted LTV, Goods Intention, Goods Phase, Search String | predicted_ltv, goods_intention, goods_phase, search_string |
| Review Email | review_email (dál nehashovat) |
| sznaiid | sznaiid |
| Include status + Status | status (true / false) |
| User/Event Data Overrides | stejné klíče v tabulkách User data / Event data |
Aliasy v User Data Object (email, phone, fname…) |
kanonické klíče em, ph, fn… |
Položky v řádku v2.x settings in use:
| Položka | Co udělat |
|---|---|
pole→user_data.klíč, pole→event_data.klíč (například userEmail→user_data.em) |
Přidejte řádek klíč do tabulky User data nebo Event data a pole vymažte. userState→user_data.region je dřívější název pole Region; použijte řádek region. |
statusEnabled→event_data.status |
Přidejte řádek status do tabulky Event data a odškrtněte Include status. |
userDataOverrides, eventDataOverrides |
Přeneste řádky do tabulky User data / Event data a staré řádky smažte. |
alias email→em |
V User Data Object použijte kanonický klíč (em). |
ga4.<klíč>, ga4.items.<klíč> |
GA4 událost obsahuje klíč mimo standard GA4 (Shoptet, MeasureHive) a šablona ho použila. Upravte data na webu na standardní GA4 klíč (transaction_id, value, items[].item_id, item_name, price, item_category…). |
testMode |
Zvolte Console logging a Test Mode odškrtněte. |
persistSznaiidCookieMode |
Zvolte last_touch. |
sznaiidCookieMaxAge |
Pole vymažte. |
Volby Auto-map event name a Strict Event Validation se v řádku neobjevují: šablona je ignoruje a jejich uloženou hodnotu nejde smazat.
-
Názvy událostí z GA4 jen 1:1.
login,add_shipping_info,view_item_list,select_itemaview_promotionse už nemapují; takový tag skončí Failed s[ERROR]Unknown event name: ga4:<název>. Namapujte je přesFrom variablenebo samostatným tagem.Auto from GA4mapuje název i bez GA4 prefill; dřívější volba Auto-map event name se ignoruje. -
Validace je vždy přísná. Neznámý název události a SEM ID mimo
^[0-9a-z]{24}$nově tag zastaví bez ohledu na Strict Event Validation; prázdný název, chybějící SEM ID a neúplný Purchase zastavovala už verze 2.3.1. Má-li tag tuto volbu uloženou vypnutou, řádek[ERROR]u těchto dvou případů končí(v2 loose validation no longer applies). Název zAuto from GA4bez mapování tuto koncovku nemá: verze 2.3.1 ho zastavila jako prázdný název. -
event_idse už nedoplňuje ztransaction_id. Pro deduplikaci s frontendem ho nastavte sami (napříkladPurchase__+ číslo objednávky). Se zapnutým GA4 prefill, bezevent_ida s vyplněnýmtransaction_idšablona zaloguje warning. -
Cookie
sznaiidukládá vždy poslední proklik (last touch) s pevnou platností 30 dní. Dřívější režim a délka platnosti se ignorují; warning se objeví jen tehdy, když by zápis změnily. -
IP adresa a User-Agent v
s2s_headersse berou z event dat GA4 klienta (ip_override,user_agent) a teprve bez nich z hlaviček requestu. Brána podle consentu se nemění. -
Use Optimistic Scenario je u nových tagů vypnuté. Šablona hlásí úspěch před odpovědí Seznamu jen tehdy, když je volba uložená jako zaškrtnutá. Doporučujeme ji vypnout, aby stav tagu odpovídal odpovědi Seznamu.
-
WARN se v produkci ve výchozím stavu nelogují. Console logging
debug(výchozí) loguje warningy a diagnostiku jen v Preview a debug režimu. Řádky[ERROR]a řádekv2.x settings in usese logují vždy. Dřívější chování dává úroveňalways. -
Chybný JSON v User Data Object nebo Event Data Object tag nezastaví. Šablona zaloguje
[ERROR], objekt vynechá a hit odešle. Purchase, kterému po sloučení vrstev chybíorder_id,currencynebovalue, tag dál zastaví. -
Chybný JSON v
contentsneboproduct_ids(starší pole Contents a Product IDs, tabulka, objekt) se vynechá s warningem. Hodnota z nižší vrstvy se neobnoví: rozbitý JSON ve starším poli Contents už nespadne zpět nacontentsz GA4 nebo z objektu. -
Platný JSON string v
contentsneboproduct_idsv Event Data Object nebo v řádku Event Data Overrides se nově rozparsuje a odešle; verze 2.3.1 ho vynechala s warningem. -
event_urlbez zdroje se neodešle. Verze 2.3.1 posílalaevent_url: "". -
Pole skrytá režimem vstupu z verze 2.x se znovu použijí. Ve verzích 2.3.0 a 2.3.1 byla jednotlivá pole User Data a Event Data dostupná jen v režimu Individual fields (volby User Data input mode / Event Data input mode) a Event/User Data Object jen v režimu Object variable. Hodnoty skrytých polí zůstaly v tagu uložené, ale GTM je šabloně nepředal. Režimy přinesla verze 2.3.0; verze 2.2.x neměla režim vstupu: objekty i jednotlivá pole byla vidět současně. Verze 3 volby i jejich podmínky odstranila, takže se každé uložené starší pole User Data a Event Data (v2.x) znovu použije (Status (bool) dál jen se zapnutým (v2.x) Include status field), a to nad Event/User Data Object (pořadí vrstev: objekt, starší pole, starší Overrides, tabulky).
- Tag vytvořený ve verzi 2.2.x nebo starší s vyplněnými jednotlivými poli nemá uložený režim. Ve verzi 2.3.x se jeho jednotlivá pole neposílala: Purchase skončil chybou
Purchase requires: …, pokudorder_id,currencyavaluenedodal GA4 Auto-Map, ostatní události odešly bez těchto polí asid/udiddoplnil cookie fallback. Verze 3 tato pole posílá znovu. - Tag přepnutý na Object variable, ve kterém zůstaly hodnoty v jednotlivých polích: tyto hodnoty nově přepíší Event/User Data Object.
- Tag s uloženým režimem Individual fields, ve kterém zůstala hodnota v Event/User Data Object: objekt se znovu použije, pod staršími poli.
Co zkontrolovat: řádek
v2.x settings in usev Preview vyjmenuje každé použité starší pole; pole, která nechcete, vymažte nebo je přesuňte do tabulek. Event Data Object a User Data Object v tomto řádku nejsou; u třetího případu je zkontrolujte přímo v tagu. - Tag vytvořený ve verzi 2.2.x nebo starší s vyplněnými jednotlivými poli nemá uložený režim. Ve verzi 2.3.x se jeho jednotlivá pole neposílala: Purchase skončil chybou
Tags->New-> zvolteSeznam SEM (Server-Side).- Nastavte povinná pole:
- Event Name: vyberte podporovanou SEM událost,
Auto from GA4, neboFrom variable. - S2S SEM ID (Sklik): S2S SEM ID ze Skliku.
- Event Name: vyberte podporovanou SEM událost,
- Doporučená pole:
- Event URL: URL stránky. Pokud zůstane prázdné, šablona použije GA4
page_location(se zapnutým GA4 prefill) neboReferer. - Event ID: unikátní ID události pro deduplikaci.
- User data: minimálně
sidaudidzesul.js(nebo je nechte načíst z cookies, viz Auto-map sid/udid z cookies), ideálně i zahashované PII.
- Event URL: URL stránky. Pokud zůstane prázdné, šablona použije GA4
- Pro ecommerce události vyplňte řádky tabulky Event data (
currency,value,order_id,contents, atd.), Event Data Object, nebo zapněte GA4 prefill. - Use Optimistic Scenario (skupina Advanced) je u nových tagů vypnuté, takže stav tagu odpovídá odpovědi API.
- Console logging (skupina Advanced) má výchozí úroveň
debug: warningy loguje jen v Preview a debug režimu. Řádky[ERROR]se logují vždy (viz Console logging).
Šablona pracuje s pevným seznamem SEM událostí. Neznámý název události tag zastaví (Failed) a nic se neodešle.
| SEM událost | GA4 zdroj (Auto from GA4) |
Poznámka |
|---|---|---|
PageView |
page_view |
|
ViewContent |
view_item |
Detail produktu / obsahu. |
Purchase |
purchase |
Výsledný payload musí obsahovat order_id, currency a value; jinak tag selže a nic neodešle. |
Contact |
contact |
|
AddToCart |
add_to_cart |
|
AddToWishlist |
add_to_wishlist |
|
InitiateCheckout |
begin_checkout |
|
AddPaymentInfo |
add_payment_info |
|
Search |
search, view_search_results |
search_term se mapuje na search_string. |
CompleteRegistration |
sign_up |
Pokud není nastavený status, šablona doplní status=true. |
Lead |
generate_lead |
|
Subscribe |
subscribe |
|
CustomizeProduct |
explicitně | Bez GA4 zdroje. |
Donate |
explicitně | Bez GA4 zdroje. |
FindLocation |
explicitně | Ponecháno, protože je stále v dokumentaci Seznamu. |
Schedule |
explicitně | Bez GA4 zdroje. |
StartTrial |
explicitně | Bez GA4 zdroje. |
SubmitApplication |
explicitně | Bez GA4 zdroje. |
| Nastavení | Chování |
|---|---|
| Vybraná konkrétní událost | Použije se vybraný SEM název. |
Auto from GA4 |
Použije se mapování 1:1 z GA4 event_name podle tabulky výše, i když je GA4 prefill vypnutý. Jiná GA4 událost (například login, add_shipping_info, view_item_list, select_item, view_promotion) tag zastaví s řádkem [ERROR] Unknown event name: ga4:<název>. |
From variable |
Použije se hodnota z GTM proměnné, ale musí být jedna z podporovaných SEM událostí. |
Šablona záměrně neposílá neznámé GA4 názvy jako custom události. Na rozdíl od Facebook CAPI není u Seznam SEM vhodné spoléhat na libovolné custom event names.
GA4 prefill je ve výchozím stavu vypnutý. Zapíná se ve skupině GA4 prefill volbou Prefill from GA4 event data. Hodnoty z objektů, tabulek i starších polí mají před předvyplněnými hodnotami přednost.
Volby:
| Volba | Výchozí stav | Popis |
|---|---|---|
enableGa4AutoMap (Prefill from GA4 event data) |
vypnuto | Hlavní přepínač. |
autoMapEventData (Prefill event data) |
zapnuto po zapnutí hlavní volby | Mapuje ecommerce a event_data pole. |
autoMapUserData (Prefill user data) |
zapnuto po zapnutí hlavní volby | Mapuje pouze předem zahashované sha256_* hodnoty z GA4 user_data. |
Název události GA4 prefill neovládá: Auto from GA4 v poli Event Name mapuje GA4 event_name i bez něj. Dřívější volba autoMapEventName je ve skupině Starší pole (v2.x) a šablona ji ignoruje.
| SEM pole | GA4 / vstupní zdroj | Poznámka |
|---|---|---|
order_id |
transaction_id -> id -> orderNo |
orderNo pomáhá například u Shoptetu. |
value |
value -> revenue -> totalWithoutVat |
Zaokrouhleno na 2 desetinná místa. Šablona value nikdy nedopočítává z položek: unit_price je s DPH, value bez DPH. |
currency |
currency |
Seznam přijímá jen CZK; jiná měna zaloguje warning. |
value_tax |
tax |
|
delivery_price |
shipping |
|
payment_type |
payment_type |
|
delivery_type |
shipping_tier |
|
search_string |
search_term |
|
event_url |
page_location |
Top-level pole payloadu. |
event_id |
event_id |
Top-level pole payloadu. transaction_id se jako event_id nepoužívá. Když chybí GA4 event_id i pole Event ID a transaction_id existuje, šablona zaloguje warning transaction_id is no longer used as event_id; set Event ID. |
SEM contents[] pole |
GA4 / vstupní zdroj | Poznámka |
|---|---|---|
id |
item_id -> id |
Povinné pro auto-mapované položky. Položky bez ID se přeskočí s warningem. |
content_name |
item_name -> name |
|
unit_price |
price -> priceWithVat -> fullPrice |
Cena za kus s DPH. Zaokrouhleno na 2 desetinná místa. |
quantity |
quantity -> 1 |
Pokud chybí, doplní se 1. Položka s množstvím 0, záporným, desetinným nebo nečíselným se zahodí s warningem (viz Contents). |
content_category |
category -> currentCategory / defaultCategory -> item_category...item_category5 |
Priorita je exkluzivní, první nalezený zdroj vyhrává. |
Příklady kategorií:
category: "A/B/C"->A | B | Citem_category: "A", item_category2: "B"->A | BcurrentCategory: ["A", "B"]->A | B
Klíče mimo standard GA4 (Shoptet, MeasureHive) šablona ve verzi 3 dál čte: id, orderNo, revenue, totalWithoutVat a u položek id, name, priceWithVat, fullPrice, category, currentCategory, defaultCategory. Když se některý z nich použije, šablona ho uvede v řádku v2.x settings in use jako ga4.<klíč>, u položek jako ga4.items.<klíč> (viz Přechod na verzi 3).
Automaticky se mapují pouze předem zahashované hodnoty:
| GA4 pole | SEM user_data pole |
|---|---|
user_data.sha256_email_address |
em |
user_data.sha256_phone_number |
ph |
user_data.address.sha256_first_name |
fn |
user_data.address.sha256_last_name |
ln |
Raw hodnoty jako email, phone, first_name, last_name se automaticky neposílají. Serverová šablona je nehashuje.
| Pole | Zdroj |
|---|---|
event_name |
Event Name nastavení, From variable, nebo Auto from GA4 |
schema_version |
konstantně v2 |
event_type |
konstantně rtgconv |
event_time |
Event Time (kladné celé číslo v ms; hodnota v sekundách se převede) nebo serverový čas. Hodnota 0, záporná nebo nečíselná se nahradí serverovým časem s warningem. |
event_source |
web nebo app |
event_url |
První použitelný zdroj: Event URL -> GA4 page_location (s GA4 prefill) -> Referer. Prázdná hodnota, 'undefined' / 'null' ani objekt se nepoužijí. Bez zdroje se event_url neodešle. |
event_id |
Event ID -> GA4 event_id (s GA4 prefill). Číslo se převede na string. |
consent_mode |
Consent Mode Object, normalizovaný (viz Consent) |
consent_string |
IAB TCF v2 consent string (viz Consent) |
user_ids.user_data |
Skupina User data |
event_data |
Skupina Event data |
s2s_headers |
IP a User-Agent z event dat GA4 klienta (ip_override, user_agent), jinak z requestu; Client Hints z requestu. Jen když je povoleno a consent granted. |
Každé pole je řádek tabulky User data se stejným klíčem. Sloupec „Starší pole (v2.x)“ uvádí dřívější jednotlivé pole, které ve verzi 3 funguje dál (viz Přechod na verzi 3).
| SEM pole / klíč řádku | Starší pole (v2.x) | Poznámka |
|---|---|---|
sid |
sid |
Hodnota ze sul.js, nehashovat. Musí mít tvar id=…|t=…|te=…|c=<32 znaků>. Pokud chybí nebo nemá tento tvar, použije se cookie sid. |
udid |
userUdid |
Hodnota ze sul.js, nehashovat. Musí to být UUID; suffix @timestamp se ořízne. Pokud chybí nebo není UUID, použije se cookie udid. |
em |
userEmail |
SHA-256 email. |
ph |
userPhone |
SHA-256 telefon. |
fn |
userFirstName |
SHA-256 jméno. |
ln |
userLastName |
SHA-256 příjmení. |
ge |
userGender |
SHA-256 gender. |
db |
userDob |
SHA-256 datum narození. |
ct |
userCity |
SHA-256 město. |
region |
userRegion (a runtime userState) |
SHA-256 region/stát. userState platí jen při prázdném userRegion. |
zp |
userZip |
SHA-256 PSČ. |
sr |
userStreet |
SHA-256 ulice. |
country |
userCountry |
SHA-256 země. |
subscription_id |
userSubscriptionId |
Identifikátor subscription. |
said, id5, secid |
— | Identifikátory podle schématu Seznamu. |
userDataObject může obsahovat přímo SEM klíče (em, ph, fn, ...). Od v2.2.1 umí šablona přeložit i frontend-style aliasy:
Alias v userDataObject |
SEM klíč |
|---|---|
email |
em |
phone |
ph |
fname |
fn |
lname |
ln |
gender, g |
ge |
birth, birthDate |
db |
postalCode, zip |
zp |
subscription, subscriptionId |
subscription_id |
Alias změní pouze název klíče. Hodnota musí být stále už zahashovaná. Při použití aliasu šablona zaloguje warning a uvede alias v řádku v2.x settings in use (například alias email→em), aby bylo vidět, že je lepší používat kanonický SEM klíč.
Ostatní klíče mimo SEM schéma user_data (em, ph, fn, ln, ge, db, ct, region, zp, sr, country, said, id5, secid, subscription_id, sid, udid) šablona neodešle a zaloguje warning. Všechny hodnoty jsou stringy; číslo se převede na string.
Každé pole kromě sem_id je řádek tabulky Event data se stejným klíčem. Sloupec „Starší pole (v2.x)“ uvádí dřívější jednotlivé pole, které ve verzi 3 funguje dál.
| SEM pole / klíč řádku | Starší pole (v2.x) | Poznámka |
|---|---|---|
sem_id |
— | Povinné S2S SEM ID, vždy z pole S2S SEM ID; sem_id v objektu nebo v tabulkách se ignoruje. |
sznaiid |
sznaiid |
Click-through ID. Když chybí, použije se URL nebo cookie. |
currency |
currency |
Seznam přijímá jen CZK; jiné měny přepočítejte před odesláním. Jiná měna zaloguje warning. |
value |
value |
Číslo, hodnota bez DPH v CZK. Povinné pro Purchase. |
value_tax |
valueTax |
Číslo, DPH k value. |
order_id |
orderId |
Povinné pro Purchase. Číslo se převede na string. |
content_type |
contentType |
Pokud existují contents a chybí content_type, doplní se product. |
contents |
contents |
Pole v SEM tvaru, JSON string téhož, nebo GA4 prefill z items[]. |
product_ids |
productIds |
Pole nezáporných integer ID produktů pro Zboží.cz, nebo JSON string téhož. |
delivery_price |
deliveryPrice |
Číslo, cena dopravy s DPH. |
delivery_type |
deliveryType |
|
payment_type |
paymentType |
|
other_costs |
otherCosts |
Číslo, další náklady nebo slevy s DPH. |
predicted_ltv |
predictedLtv |
Číslo. |
goods_intention |
goodsIntention |
Číslo. |
goods_phase |
goodsPhase |
Integer; jiná hodnota se vynechá s warningem. |
search_string |
searchString |
Hlavně pro Search. |
review_email |
reviewEmail |
Plain text, nehashovat. |
status |
statusEnabled + status |
Boolean (true / false). Starší pole Status platí jen se zaškrtnutým Include status. |
Po sloučení všech vrstev šablona projde výsledný payload jednou a každou hodnotu převede na typ podle SEM schématu:
- Klíč mimo schéma
event_data,user_datanebo položkycontentsse neodešle a zaloguje se warning. - Čísla: JS číslo nebo desetinný řetězec s tečkou (
'1234.50','-5'). Řetězce'1 234,50','1,234','1e3'a'Infinity'jsou neplatné; šablona nehádá formát čísla podle locale. - ID (
order_id,event_id,sznaiid,contents[].id, hodnotyuser_data): neprázdný string; číslo se převede na string (0→"0"). - Řetězce
'undefined'a'null'(typický výsledek rozbitého mapování proměnné) se ve všech klíčích kromě volného textu (search_string,content_name,content_category) berou jako nevyplněné: nepřepíšou hodnotu z dřívější vrstvy a šablona zaloguje warning. Ve volném textu zůstanou jako slova. status:true/false,1/0,'true'/'false', ze všech vrstev včetně staršího pole Status. Zaškrtnuté Include status bez hodnoty odešlefalse.content_type:page,product,product_groupnebosearch. Jiná hodnota se vynechá s warningem; když zůstanoucontents, doplní seproduct.- GA4 prefill bere jako ID jen string nebo konečné číslo. Objekt, boolean, pole, NaN nebo Infinity v
transaction_idčiitem_idpřeskočí a použije další zdroj (id,orderNo). - User Data Object a Event Data Object: prázdný řetězec znamená nevyplněno. Nečitelný JSON nebo jiný typ (
false,0, číslo) šablona vždy zaloguje jako[ERROR]a objekt vynechá; hit pokračuje k validaci. Purchase bezorder_id,currencyavaluepo sloučení vrstev tag zastaví. contentsaproduct_idsjako JSON string z libovolné vrstvy (tabulka, objekt, starší pole, overrides) šablona rozparsuje až po sloučení vrstev. Nečitelná hodnota nebo hodnota, která není pole, se vynechá s warningem a hodnota z nižší vrstvy se neobnoví.- Řetězce se ořežou o mezery na začátku a na konci.
- Neplatná nepovinná hodnota se vynechá s warningem. Neplatná povinná hodnota (
order_id,currency,valueu Purchase) tag zastaví. - Chybějící hodnota (
undefined,null, prázdný řetězec) nic nepřepisuje.false,0a[]jsou hodnoty.
Pokud nepoužíváte GA4 prefill, contents posílejte v nativním SEM tvaru, jako pole z GTM proměnné nebo jako JSON string (řádek contents v tabulce Event data):
[
{
"id": "SKU-123",
"quantity": 2,
"unit_price": 249.9,
"content_name": "Modrá čepice",
"content_category": "Příslušenství | Čepice"
}
]| Pole | Typ | Poznámka |
|---|---|---|
id |
string | SKU nebo produktové ID. |
quantity |
integer ≥ 1 | Počet kusů. Chybějící množství šablona odešle jako 1. |
unit_price |
number | Cena za kus s DPH. |
content_name |
string | Název produktu/obsahu. |
content_category |
string | Kategorie, například `Elektronika |
Pravidla pro contents ze všech zdrojů (GA4 prefill, Event Data Object, tabulka Event data, starší pole Contents a overrides):
- Chybějící
quantityi řetězec'null'/'undefined'šablona odešle jako1; řetězec zaloguje warning. - Položka, jejíž
quantityje vyplněné, ale není celé číslo alespoň 1 (0, záporné,0.5,1.9,'abc',Infinity), se zahodí s warningem. Ostatní položky i událost se odešlou. - Položka nepotřebuje žádný konkrétní klíč (schéma žádný nevyžaduje); šablona ponechá i položku bez
id,content_nameacontent_category. - Když se zahodí všechny položky,
contentsse neodešle a šablona nedoplní anicontent_type. Explicitně vyplněnécontent_typezůstane. - Explicitně předané prázdné pole
[]se odešle jako[]. - Klíče mimo tabulku výše se zahodí s warningem.
Ve výchozím stavu je zapnuté ukládání sznaiid do first-party cookie.
Chování:
- Šablona hledá
?sznaiid=...v GA4page_location. - Pokud ho nenajde, zkusí
Referer. - Pokud je zapnutá cookie persistence, uloží hodnotu do cookie
sznaiid. Nový proklik vždy přepíše existující cookie a obnoví její platnost (last touch), stejně jakosem.js. - Na dalších událostech bez URL parametru použije hodnotu z cookie.
sznaiidz tabulky Event data, z Event Data Object nebo ze staršího pole má vždy přednost.
Dřívější nastavení Cookie write strategy (first_touch / last_touch) a Cookie max-age jsou ve skupině Starší pole (v2.x) a šablona je ignoruje. V řádku v2.x settings in use se objeví jen tehdy, když by zápis změnily: uložené first_touch při existující cookie, nebo uložená délka jiná než 2592000 s. Cookie s délkou 90 dní zapsané starší verzí zůstanou, dokud je nový proklik nepřepíše nebo nevyprší.
Vypnutí persistSznaiidCookie vypne čtení i zápis cookie, ale URL hodnota ?sznaiid=... se stále může poslat v payloadu.
Šablona cookie zapíše až poté, co payload projde validací. Když tag selže (například chybný consent nebo neúplný Purchase), cookie se nezapíše. Atributy: Path=/, doména auto, Secure, SameSite=Lax, bez HttpOnly, Max-Age pevně 2592000 s (30 dní). Podle dokumentace Seznamu lze sznaiid uložit i bez souhlasu uživatele.
Od verze 2.3 umí šablona načíst sid a udid z příchozích request cookies jako fallback. Ovládá to checkbox Auto-map sid & udid from request cookies (fallback) v sekci User Data, ve výchozím stavu zapnutý.
Jak to funguje:
- Pokud je
sid/udidvyplněné explicitně (řádek tabulky User data, User Data Object nebo starší pole) a má správný tvar, použije se ta hodnota. Cookie fallback má nejnižší prioritu a doplní hodnotu, když explicitní hodnota chybí nebo nemá správný tvar. sidse čte z cookiesid. Hodnota obsahuje=(id=...|t=...|te=...|c=...), ale čte se celá.udidse čte z cookieudid. Suffix<uuid>@<timestamp>, který nastavujesul.js, se ořízne na samotnéuuid.- Explicitní hodnoty i hodnoty z cookies se validují proti stejnému tvaru (UUID pro
udid,id=…|t=…|te=…|c=<32 znaků>prosid). Nevalidní hodnota se zahodí a zaloguje se WARN; hodnota se do logu nevypisuje. Kontrola chrání proti chybně namapovaným proměnným i uživatelsky podvrženým cookies. - Když payload nakonec neobsahuje platné
sid, šablona zaloguje WARNno valid sid, i když obsahuje jiné identifikátory.
Předpoklady:
- Same-site SGTM endpoint, aby cookies vůbec dorazily do server containeru (viz SGTM endpoint musí být na stejném webu).
- Consent: šablona vidí jen příchozí cookie, ne podmínky, za kterých vznikla.
sul.jsvytvářísidaž po udělení souhlasu. Šablona stejně jako u explicitních polí předáváuser_idsspolu sconsent_mode; vyhodnocení consentu je na straně Seznamu (viz Consent). Pokud chcete být striktnější, fallback vypněte a posílejtesid/udidjen explicitně. - Safari (ITP): WebKit maže cookies vytvořené JavaScriptem, tedy i
sidaudid, po 7 dnech bez interakce uživatele s webem (WebKit Tracking Prevention). Dokud jesul.jsznovu nevytvoří, fallback je nedoplní.
Pokud cookies do SGTM dorazí, nemusíte sid/udid posílat jako GA4 event parametry (ep.sid/ep.udid).
event_id je doporučené pro deduplikaci. Pokud posíláte stejnou konverzi z frontendu i ze serveru, musí být event_id na obou stranách stejné.
Pozor: některé frontendové šablony pro Purchase automaticky generují event_id ve tvaru:
Purchase__<order_id>
Tato serverová šablona takové ID záměrně automaticky nevytváří. Pokud chcete deduplikovat frontend a server, nastavte Event ID na stejnou hodnotu jako na frontendu.
Pole se skládají ve vrstvách. Pozdější vrstva přepisuje předchozí. Pro event_data:
- GA4 prefill - pokud je zapnutý. Patří sem i
contentsz GA4items[]. - Event Data Object.
sznaiidz URL nebo cookie - jen kdyžsznaiidzatím chybí.- Starší jednotlivá pole (v2.x) a starší Status.
- Starší tabulka Event Data Overrides (v2.x).
- Tabulka Event data.
Pro user_ids.user_data:
- GA4 prefill (jen
sha256_*hodnoty). - User Data Object (aliasy přeložené na kanonické klíče).
- Starší jednotlivá pole (v2.x).
- Starší tabulka User Data Overrides (v2.x).
- Tabulka User data.
- Cookie fallback
sid/udid- až po všech vrstvách, jen doplní chybějící nebo neplatnou hodnotu.
Po sloučení vrstev šablona výsledný payload jednou normalizuje (viz Typová normalizace) a jednou validuje: název události, S2S SEM ID a u Purchase order_id, currency a value. Validuje se přesně ten payload, který se odešle.
Speciální případy:
- Hodnota, která není vyplněná, nikdy nepřepíše hodnotu z dřívější vrstvy. Nevyplněná je hodnota
undefined,null, prázdný řetězec a řetězec'undefined'/'null'(ten ve všech klíčích kromě volného textusearch_string,content_name,content_category). NapříkladeventDataObjectsorder_id: nullneboorder_id: 'null'ponecháorder_idz GA4 prefill. false,0a[]jsou hodnoty. Vyplněná, ale neplatná hodnota přepíše dřívější vrstvu a pak ji normalizace vynechá s warningem; šablona se k dřívější hodnotě nevrací.contentsz Event Data Object, tabulky Event data, staršího pole Contents nebo overrides, včetně prázdného[], nahradícontentsz GA4 prefill.sid/udidz cookies (sid,udid) jsou fallback až po tabulce User data - doplní se jen když z předchozích vrstev chybí platná hodnota. Viz Auto-map sid/udid z cookies.sem_idvždy pochází z pole S2S SEM ID.- Tabulky umí přidat nebo přepsat pole, ale neumí pole odstranit.
Skupiny Event data a User data mají tabulku Klíč – Hodnota. Klíč vybíráte ze seznamu SEM klíčů (každý klíč nejvýš jednou), hodnotu zadáte textem nebo GTM proměnnou.
- Řádky tabulky mají nejvyšší prioritu: přepíšou GA4 prefill, objekt i starší pole.
- Hodnota se převede na typ daného klíče (čísla,
true/falseprostatus,contentsaproduct_idsjako pole nebo JSON string). Neplatná hodnota se vynechá s warningem. - Řádek s prázdnou hodnotou nebo s řetězcem
'undefined'/'null'nic nepřepíše;falsea0jsou hodnoty. - Tabulka neumí pole odstranit.
em,ph,fn,ln,ge,db,ct,region,zp,sracountrymusí být SHA-256 hashe z frontendu.sid,udidasubscription_idse posílají tak, jak jsou;sidaudidšablona kontroluje na tvar.
Starší tabulky User Data Overrides a Event Data Overrides (klíč zapsaný textem) jsou ve skupině Starší pole (v2.x). Fungují dál s prioritou těsně pod novými tabulkami. Klíč mimo SEM schéma šablona neodešle a zaloguje warning.
Šablona čte consent jen z polí Consent Mode Object a Consent String (IAB TCF) ve skupině Consent. Nečte ho z GA4 event dat (ani z parametrů x-ga-gcs / x-ga-gcd) ani z cookies CMP. Stav souhlasu proto musíte do SGTM přenést sami a namapovat ho v každém SEM tagu.
Varianta A: parametr GA4 události. GA4 omezuje hodnotu parametru události na 100 znaků a počítá délku po URL kódování (limity sběru událostí GA4). Pošlete proto jen tři reklamní klíče, s hodnotami 1 (granted) a 0 (denied), které šablona přijímá:
{"ad_storage":1,"ad_user_data":1,"ad_personalization":0}Tato hodnota má 56 znaků, po URL kódování 82. Tvar s řetězci, {"ad_storage":"granted","ad_user_data":"granted","ad_personalization":"granted"}, má 80 znaků, ale po URL kódování 118, tedy nad limitem.
- Na webu přidejte do GA4 události parametr
sem_consents touto hodnotou, sestavenou ze skutečné volby uživatele v CMP. - V SGTM vytvořte proměnnou typu Event Data s Key Path
sem_consent. - Proměnnou přiřaďte do pole Consent Mode Object v každém SEM tagu.
Částečný consent_mode je platný: schéma vyžaduje alespoň jeden podporovaný klíč (anyOf), ne všech pět. Šablona chybějící klíče nedoplňuje. Klíče ad_storage a ad_user_data otevírají bránu pro s2s_headers.
Varianta B: objekt přes Data Tag a Data Client. Testovací kontejner předává stav souhlasu jako objekt consent_state v event datech z Data Clientu: proměnná Event Data consent_state je v Purchase tagu namapovaná do Consent Mode Object a všech 8 zalogovaných Purchase hitů z tohoto tagu obsahovalo consent_mode. Nejde o parametr GA4 události, takže se na něj limit 100 znaků nevztahuje. Hodnoty true/false i granted/denied šablona převede.
U obou variant ověřte v sGTM Preview, že proměnná obsahuje celou hodnotu: objekt nebo JSON string objektu s podporovanými klíči, ne zkrácený řetězec ani obal typu {"consent_mode": {...}}. Zkrácený JSON nejde rozparsovat a tag pak podle pravidla pro chybný consent selže.
Podporované klíče: ad_storage, ad_user_data, ad_personalization, functionality_storage, analytics_storage.
| Vstup | Odešle se |
|---|---|
'granted', true, 1, '1', 'true' |
granted |
'denied', false, 0, '0', 'false' |
denied |
- Mezery na začátku a na konci řetězce se ignorují (
' granted 'jegranted). Velikost písmen se nemění:'Granted'je chyba. - Klíče, které v objektu jsou, se odešlou. Chybějící klíče šablona nedoplňuje.
- Ostatní klíče (například
wait_for_update) se ignorují. - Prázdná hodnota a řetězce
'undefined'/'null'znamenají, že klíč není vyplněný. - Hodnota
nulltaké znamená, že klíč není vyplněný: šablona ho vynechá, zaloguje warning a nedoplní ho jakograntedanidenied. - Když žádný podporovaný klíč nemá hodnotu a Consent String není vyplněný, šablona
consent_modeneodešle, hit odešle a zaloguje warningno consent signal.
Pokud je pole vyplněné, ale chybné, tag skončí jako Failed (gtmOnFailure), nic neodešle a nezapíše cookie sznaiid. Platí to vždy. Chybou je:
- Consent Mode Object, který není objekt ani JSON string objektu, nebo nejde rozparsovat;
- objekt bez podporovaného klíče, například obal
{"consent_mode": {...}}; - neplatná hodnota u podporovaného klíče, například
'Granted','yes'nebo číslo jiné než0a1; - Consent String, který nezačíná
Cnebo obsahuje jiné znaky nežA-Z,a-z,0-9,_,.,-.
Šablona zaloguje jeden řádek ve tvaru Seznam SEM [ERROR]: <pole>: <problém>, got <typ>, například Seznam SEM [ERROR]: consentModeObject: expected object with granted/denied values, got string. Řádek nikdy neobsahuje hodnotu souhlasu. Loguje se vždy, nezávisle na nastavení Console logging: v sGTM Preview je na záložce Console a v produkci v serverových logách (Cloud Logging). Do DevTools prohlížeče se nedostane, protože tag běží na serveru.
Seznam vyhodnocuje TCF consent string přednostně před consent_mode („Systém vždy upřednostní IAB TCF“, dokumentace Seznamu k consentu; v S2S payloadu „bude upřednostněn“). Pole Consent String (IAB TCF) proto vyplňte jen tehdy, když vaše CMP je IAB TCF v2 a má Seznam ve vendor listu. Jinak ho nechte prázdné.
Šablona kontroluje jen syntaxi (první znak C, povolené znaky). Kontrola neověřuje, že string je platný TCF ani že obsahuje souhlas pro Seznam; to vyhodnotí Seznam.
- Předá
consent_modeaconsent_stringSeznamu. - Hity podle consentu neblokuje.
user_ids,review_emailasznaiidse odešlou bez ohledu na stav souhlasu; vyhodnocení je na straně Seznamu. V testovacím kontejneru dostaly odpověď200i hity bez consentu nebo bezsid/udid; samotná odpověď200nedokládá, jak Seznam vyhodnotil consent ani atribuci. s2s_headers(IP adresa, User-Agent, Client Hints) pošle jen když je zapnutésendS2sHeadersa zároveňconsent_mode.ad_storageiconsent_mode.ad_user_datajsougranted.- Brána pro
s2s_headersčte jenconsent_mode. Nastavení jen s TCF stringem (bez Consent Mode Object) protos2s_headersnikdy neodešle. - Když se loguje diagnostika (Console logging
always, nebodebugv Preview), zaloguje u každého requestu souhrn consentu, surovou hodnotu GA4x-ga-gcs(jen do logu, do payloadu se nepřevádí) a zdrojsid/udid.
Ověřeno v testovacím kontejneru 26. 10. 2026 (web s cookie lištou bez IAB TCF, SEM tag s GA4 Auto-Map verze 2.3):
| Hit | Consent | GA4 tag | SEM tag |
|---|---|---|---|
page_view před souhlasem (gcs=G100) |
denied | spustil se | spustil se |
stejný page_view znovu odeslaný po kliknutí na „Přijmout“ (gcs=G111, gcu=1) |
granted | spustil se | nespustil se |
nový běžný page_view na další stránce (gcs=G111, bez gcu) |
granted | spustil se | spustil se |
Trigger SEM tagu neměl žádnou podmínku na consent ani na gcu. SGTM tedy na automaticky znovu odeslaném hitu (gcu=1) SEM tag nespustí, a pro vstupní stránku dostane SEM jen hit z doby před souhlasem. Šablona to opravit nemůže, protože se na znovu odeslaném hitu vůbec nespustí. Nové běžné události odeslané po udělení souhlasu SEM tag spouštějí normálně.
Stejné chování popisují Simo Ahava (30. 4. 2024) a dokumentace Stape Event Generator (14. 4. 2026). Google parametr x-ga-gcu uvádí mezi interními parametry, pravidlo potlačení tagů ale nedokumentuje.
Doporučený postup:
- CMP načtěte před GTM, nastavte výchozí stav (
default) i aktualizaci (update) await_for_update. - Po udělení souhlasu (a pokud potřebujete
sid, po načtení identity zesul.js) odešlete samostatnou běžnou událost, napříkladsem_consent_ready. - Na tuto událost spusťte SEM tag s explicitně nastaveným Event Name
PageView. Auto mapování názvu z GA4 pomocnou událost nezná. - Sjednoťte triggery a Event ID tak, aby se PageView nezapočítal dvakrát, a pomocnou událost podle potřeby vynechte z přeposílání do GA4. Nákupy znovu neodesílejte.
Ověření v sGTM Preview: původní hit se souhlasem denied, znovu odeslaný hit s x-ga-gcu a seznam tagů, které se na něm spustily.
Nastavení Console logging (logType) ve skupině Advanced určuje, které řádky šablona zapíše do logu (sGTM Preview → Console, v produkci Cloud Logging):
| Úroveň | [WARN] a diagnostika requestu a odpovědi |
|---|---|
no (Do not log) |
nelogují se |
debug (Preview and debug only), výchozí |
jen v Preview a debug režimu kontejneru |
always (Always) |
vždy, i v produkci |
- Řádky
[ERROR]se logují vždy. - Řádek
v2.x settings in use(viz Přechod na verzi 3) se loguje vždy. - Režim Preview/debug šablona zjišťuje přes
getContainerVersion(oprávněníread_container_data). Když informace o kontejneru chybí, šablona se chová jako v produkci. - Zaškrtnutý starší Test Mode vynutí úroveň
always. - Verze 2.3.1 logovala warningy vždy. Ve verzi 3 se v produkci ve výchozím stavu nelogují; pro dřívější chování zvolte
always.
BigQuery logging je volitelné a ve výchozím stavu vypnuté. Zapne se nastavením BigQuery Log Type = always a vyplněním Project / Dataset / Table v sekci BigQuery Logs.
Tabulku (a případně dataset) si vytvoř předem. Šablona zapisuje tyto sloupce:
| Sloupec | Typ | Obsah |
|---|---|---|
tag_name |
STRING | vždy "Seznam SEM" |
event_name |
STRING | vyhodnocený název události, pokud je k dispozici (např. Purchase) |
request_method |
STRING | "POST" |
request_url |
STRING | endpoint API |
request_body |
STRING | JSON string odeslaného payloadu |
timestamp |
INT64 | epoch v milisekundách |
request_id |
STRING | hlavička x-request-id z odpovědi |
response_status_code |
INT64 | HTTP status |
response_headers |
STRING | JSON string hlaviček odpovědi |
response_body |
STRING | tělo odpovědi API |
-- dataset (pokud ještě neexistuje)
CREATE SCHEMA IF NOT EXISTS `PROJECT.DATASET`;
CREATE TABLE `PROJECT.DATASET.sem_log`
(
tag_name STRING,
event_name STRING,
request_method STRING,
request_url STRING,
request_body STRING,
timestamp INT64,
request_id STRING,
response_status_code INT64,
response_headers STRING,
response_body STRING
)
PARTITION BY DATE(_PARTITIONTIME); -- ingestion-time partitioning (volitelné)Poznámky:
- Celou cestu
PROJECT.DATASET.TABLEuzavři do backticks (povinné, když project ID obsahuje pomlčky). timestampmusí být INT64, ne TIMESTAMP — šablona vkládá milisekundy jako číslo. V dotazech převedeš přesTIMESTAMP_MILLIS(timestamp).- Všechny sloupce NULLABLE. U validační nebo konfigurační chyby (před odesláním) se vyplní
tag_name,event_name,request_method,request_url,timestampa doresponse_bodytext chyby;request_body,request_id,response_status_codearesponse_headerszůstanou NULL. U requestu, který selhal bez HTTP odpovědi (timeout, síťová chyba), se vyplní request část včetněrequest_bodya response sloupce zůstanou NULL. - Zápis probíhá s
ignoreUnknownValues: true, takže sloupce navíc v tabulce nevadí, ale názvy/typy výše musí sedět.
Dotaz ukáže za posledních 30 dní pro každou verzi šablony a událost podíl hitů se sid a udid a počty hitů s problémy ze sekce Nejčastější problémy v datech. Počítá jen odeslané requesty (request_body není NULL). Hit zastavený validací (například Purchase bez order_id od verze 2.3.1) má request_body NULL a text chyby v response_body; sloupec purchase_bez_order_id proto zachytí jen starší verze. Sloupec bez_consent_mode počítá i hity, které nesou jen consent_string (IAB TCF).
SELECT
JSON_VALUE(request_body, '$.api.template_version') AS verze,
event_name,
COUNT(*) AS hity,
ROUND(100 * COUNTIF(JSON_VALUE(request_body, '$.user_ids.user_data.sid') IS NOT NULL) / COUNT(*), 1) AS se_sid_pct,
ROUND(100 * COUNTIF(JSON_VALUE(request_body, '$.user_ids.user_data.udid') IS NOT NULL) / COUNT(*), 1) AS se_udid_pct,
COUNTIF(JSON_QUERY(request_body, '$.consent_mode') IS NULL) AS bez_consent_mode,
COUNTIF(JSON_VALUE(request_body, '$.consent_mode.ad_storage') = 'denied') AS ad_storage_denied,
COUNTIF(event_name = 'Purchase' AND JSON_VALUE(request_body, '$.event_data.order_id') IS NULL) AS purchase_bez_order_id,
COUNTIF(EXISTS(
SELECT 1 FROM UNNEST(JSON_QUERY_ARRAY(PARSE_JSON(request_body), '$.event_data.contents')) AS polozka
WHERE JSON_QUERY(polozka, '$.quantity') IS NOT NULL
AND (
JSON_TYPE(JSON_QUERY(polozka, '$.quantity')) != 'number'
OR NOT REGEXP_CONTAINS(JSON_VALUE(polozka, '$.quantity'), r'^[1-9][0-9]*$')
)
)) AS neplatne_quantity,
COUNTIF(REGEXP_CONTAINS(request_body, r'[:,\[]null[,}\]]|"(undefined|null)"')) AS null_nebo_undefined
FROM `PROJECT.DATASET.sem_log`
WHERE request_body IS NOT NULL
AND TIMESTAMP_MILLIS(timestamp) >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY verze, event_name
ORDER BY verze, hity DESC;Sloupec null_nebo_undefined hledá v celém payloadu hodnotu null a texty "undefined" / "null", tedy i ve volných textech (content_name, search_string); řádky s nenulovým počtem si projděte. Zastavené hity podle chyby spočítáte dotazem nad řádky s request_body IS NULL, seskupenými podle REGEXP_REPLACE(response_body, r' \| trace=\S+', ''). U chyby validace obsahuje text | event=<název> a, když request nese hlavičku trace-id, i | trace=<id>, který může být pro každý hit jiný.
Šablona má v access_bigquery permission wildcard scope (projectId: *, datasetId: *, tableId: *, operation: write). GTM Custom Template permissions jsou statické a nejdou navázat na runtime hodnoty parametru.
Efektivní omezení zápisu řešte přes IAM na sGTM service accountu:
- service account by měl mít
roles/bigquery.dataEditorjen na konkrétní dataset, - ideálně ve vlastním projektu mimo produkční data,
- pokud BigQuery logging nepoužíváte, nedávejte service accountu BigQuery oprávnění.
| Problém | Řešení |
|---|---|
| Tag skončí jako Failed hned, bez requestu | V Console sGTM Preview najděte řádek Seznam SEM [ERROR]. Jmenuje pole a problém: chybějící nebo neznámý Event Name, chybějící SEM ID nebo SEM ID mimo ^[0-9a-z]{24}$, chybný consent, neúplný Purchase. Konec řádku (v2 loose validation no longer applies) u neznámého názvu události nebo chybného SEM ID znamená, že tag má uloženou dřívější volbu Strict Event Validation vypnutou: verze 2.3.1 by takový hit odeslala, verze 3 ho zastaví vždy. |
[ERROR] consentModeObject… nebo [ERROR] consentString… |
Consent Mode Object nebo Consent String je vyplněný, ale chybný. Opravte mapování proměnné podle sekce Consent. |
[ERROR] userDataObject: …; omitting it (nebo eventDataObject) |
Objekt není čitelný JSON ani objekt. Šablona ho vynechala a hit odeslala bez jeho hodnot. Opravte proměnnou. |
invalid JSON u JSON, který je jinak platný |
JSON vnořený hlouběji než 64 úrovní šablona bere jako neplatný; pole Seznamu, která šablona z JSON čte, mají nejvýš 3 úrovně. Posílejte v proměnné jen pole Seznamu. |
[ERROR] na SEM ID |
S2S SEM ID musí mít 24 znaků z 0-9 a a-z; jiná hodnota tag zastaví. |
| HTTP 401 / 403 | Podle dokumentace Seznamu může 401/403 znamenat chybné SEM ID nebo nepřístupný endpoint. Zkontrolujte, že je v tagu S2S SEM ID ze Skliku, ne SEM ID ze sul.js. |
| Purchase selhává | Výsledný payload (po všech vrstvách a normalizaci) musí obsahovat order_id, currency a číselné value bez DPH. Šablona value nedopočítává z položek. ERROR řádek jmenuje chybějící pole. |
Warning … is not a Seznam field |
Klíč není v SEM schématu a šablona ho neodešle. Přejmenujte ho na SEM klíč nebo ho odstraňte. |
Warning …: expected number…; omitting |
Hodnota není číslo ani desetinný řetězec s tečkou. Opravte formát na webu (1234.50, ne 1 234,50). |
Warning … is the placeholder string "undefined" |
Proměnná se vyhodnotila na text undefined nebo null. Šablona hodnotu bere jako nevyplněnou; opravte mapování proměnné. |
Warning …quantity…; dropping the item |
Položka má množství 0, záporné, desetinné nebo nečíselné a neodešle se. Opravte data na webu; chybějící množství šablona doplní jako 1. |
Warning no valid sid |
Do SGTM nedorazila platná cookie sid ani platná explicitní hodnota. U CMP bez IAB TCF zkontrolujte volání SEM('updateConsent', …) (bez něj sul.js sid nevytvoří), dále same-site endpoint a načtení sul.js před GA4. |
Warning no consent signal |
Consent Mode Object ani Consent String nejsou v tomto tagu vyplněné, nebo mají všechny klíče prázdnou hodnotu. Namapujte Consent Mode Object v každém SEM tagu, včetně tagů s GA4 prefill (viz Přenos stavu souhlasu do SGTM). |
[ERROR] Unknown event name |
Název události musí být jeden z 18 podporovaných SEM eventů. ga4:<název> je GA4 událost bez mapování 1:1 (viz Podporované události); namapujte ji přes From variable nebo samostatným tagem s pevným Event Name. |
Warning v2.x settings in use |
Tag používá starší pole z verze 2.x. Postup je v sekci Přechod na verzi 3. |
Warning transaction_id is no longer used as event_id |
Nastavte Event ID (například Purchase__ + číslo objednávky), pokud deduplikujete frontend a server. |
| V produkčních logech nejsou warningy | Console logging debug loguje warningy jen v Preview a debug režimu. Zvolte always (viz Console logging). |
Chybí event_url |
Vyplňte Event URL, zapněte GA4 prefill (page_location), nebo zajistěte Referer. Bez zdroje se event_url neodešle a šablona zaloguje warning. |
| Chybí user_ids | Předávejte minimálně sid a udid ze sul.js, případně zahashované PII. |
| User data se posílají jako raw PII | Hashování musí proběhnout na frontendu před příchodem do SGTM. Serverová šablona nehashuje. |
sznaiid se neukládá do cookie |
Zkontrolujte, že je zapnuté persistSznaiidCookie, request obsahuje ?sznaiid=..., tag běží mimo GTM preview ping a tag neselhal (cookie se zapisuje až po úspěšné validaci). |
| API errors | Zkontrolujte S2S SEM ID, payload shape a error logs (obsahují x-request-id). Tělo chybové odpovědi Seznamu je v diagnostickém řádku Response (Console logging always, nebo debug v Preview). Při ladění vypněte optimistic scenario. Request má timeout 5 s. |
Šablona obsahuje vestavěné testy (záložka Tests v editoru šablony). Postup spuštění:
- Ve formuláři Template Preview napište do pole S2S SEM ID (Sklik) libovolnou hodnotu a neukládejte ji. Pole je povinné; dokud je prázdné, editor testy nespustí a v konzoli hlásí
Invalid input in Template Preview. - Spouštějte testy po jednom tlačítkem ▶ u každého testu. Spuštění všech testů najednou skončí chybou
Invalid input: GTM odmítne požadavek se šablonou a všemi testy (402 574 znaků v běhu z 29. 10. 2026) a požadavek s jedním testem přijme (259 397 znaků). - Editor posílá testy na Server container URL z Admin → Container Settings. Když tato adresa neodpoví na CORS preflight z
https://tagmanager.googleusercontent.com, editor hlásíUnable to connect to the tag server.