Šablony a personalizace
Šablona a její obsah
Šablona (template) má název, předmět, preheader a obsah. Obsah je {editor, html, design, version}:
editor: "html": obsah je HTML,designjenull. Pro API nejjednodušší.editor: "visual": obsah vizuálního editoru (MJML) vdesign({"format": "mjml-1", "mjml", "styles"}) a z něj vykreslenéhtml.
Založení se zkopírovaným obsahem jedním voláním:
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/templates" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"name": "Opuštěný košík",
"subject": "{{df_name|default('Dobrý den', true)}}, něco jste nechali v košíku",
"preheader": "Váš košík na vás počká ještě pár dní",
"content": {
"editor": "html",
"design": null,
"html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>ve vašem košíku zůstalo {{ metadata.event.attributes.itemCount }} ks zboží za {{ metadata.event.attributes.total }} {{ metadata.event.attributes.currency }}.</p><p><a href=\"https://www.example.cz/kosik/\">Dokončit objednávku</a></p><p style=\"font-size:12px\">{{cl_company}}, {{cl_address}}. <a href=\"{{unsubscribe}}\">Odhlásit odběr</a></p></body></html>"
}
}
JSON{
"id": "301",
"name": "Opuštěný košík",
"subject": "{{df_name|default('Dobrý den', true)}}, něco jste nechali v košíku",
"preheader": "Váš košík na vás počká ještě pár dní",
"editor": "html",
"createdAt": "2026-10-01T08:00:00.000Z",
"updatedAt": "2026-10-01T08:00:00.000Z",
"tags": [],
"size": 465,
"archived": false,
"archivedAt": null,
"readOnly": false,
"usage": {
"campaigns": 0,
"automations": 0
},
"lastUsedAt": null,
"check": {
"errors": [],
"warnings": [
"subject_long"
],
"checkedAt": "2026-10-01T08:00:00.000Z"
},
"content": {
"editor": "html",
"html": "<!doctype html><html><body><p>Dobrý den, {{df_salution|default('vážený zákazníku', true)}},</p><p>ve vašem košíku zůstalo {{ metadata.event.attributes.itemCount }} ks zboží za {{ metadata.event.attributes.total }} {{ metadata.event.attributes.currency }}.</p><p><a href=\"https://www.example.cz/kosik/\">Dokončit objednávku</a></p><p style=\"font-size:12px\">{{cl_company}}, {{cl_address}}. <a href=\"{{unsubscribe}}\">Odhlásit odběr</a></p></body></html>",
"design": null,
"version": 1,
"updatedAt": "2026-10-01T08:00:00.000Z"
},
"settings": {
"linkParams": [],
"headers": [],
"unsubscribePageId": null,
"footerId": null
},
"draft": {
"pending": false,
"savedAt": null,
"publishedAt": null
},
"activeUses": {
"automations": 0,
"emails": 0,
"campaigns": 0
},
"publicUrl": "https://links.example.cz/template/1/72cf576a-85b2-474e-86e2-bfdbd1f4d38f"
}Úprava obsahu: PUT /templates/{id}/content s {editor, html, design, baseVersion}; baseVersion je verze, kterou jste načetli (u nové šablony 1). Jiná verze na serveru = 409 conflict / version s params.current. Každé uložení se zapíše do historie (GET /templates/{id}/versions).
- HTML server před uložením vyčistí: žádné skripty, rámy, atributy
on*, odkazyjavascript:ani nebezpečné CSS. Čistý vstup zůstane beze změny. - HTML nad 102 000 bajtů hlásí kontrola obsahu jako chybu a takový e-mail neodejde (Gmail delší e-mail ořízne).
- Kampaň má vlastní kopii obsahu (
PUT /campaigns/{id}/content); pozdější úprava šablony kampaň nezmění.
Šablona, kterou posílá zapnutá automatizace
Aby se omylem nezměnil e-mail, který právě chodí zákazníkům, uloží se změna obsahu takové šablony do konceptu. E-maily posílají dál publikovanou podobu, dokud koncept nepublikujete:
POST /templates/{id}/publishs{"confirm": "<přesný název šablony>"}(klíčem API; přihlášený člověk posílá heslo).DELETE /templates/{id}/draftkoncept zahodí.- Smazat šablonu, kterou posílá zapnutá automatizace, nejde (409
conflict/in_use).
Kontrola obsahu
POST /content/lint s {html, subject, preheader} vrátí issues s kódy (chyby první). Stejná kontrola běží při schválení kampaně a zapnutí automatizace: chyba odeslání zastaví, upozornění ne.
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/content/lint" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"html": "<p>Dobrý den, {{df_jmeno}}</p>",
"subject": "Podzimní novinky",
"preheader": ""
}
JSON{
"issues": [
{
"code": "unknown_tag",
"severity": "error",
"params": {
"tags": "{{df_jmeno}}"
}
},
{
"code": "no_unsubscribe",
"severity": "warning",
"params": {}
}
]
}| Kód | Závažnost | Kdy |
|---|---|---|
subject_missing | chyba | prázdný předmět |
subject_too_long | chyba | předmět nad 200 znaků |
content_empty | chyba | žádný text ani obrázek |
unknown_tag | chyba | neznámá zástupná značka (params.tags) |
foreign_tag | chyba | značky jiných nástrojů (*|X|*, %%x%%, {$x}) |
script_error | chyba | skript Twig nejde spustit (params.line, params.detail) |
unsupported_filter | chyba | nepodporovaný filtr (například |raw) |
bad_fallback | chyba | neplatná náhrada default(...) |
emoji | chyba | emoji, když je firma zakázala |
forbidden_word | podle pravidla | zakázané slovo podle pravidel firmy |
image_placeholder, image_data_uri | chyba | nenahrazený zástupný obrázek, obrázek vložený jako data: |
banned_host | chyba | odkaz nebo obrázek na zakázaném hostiteli |
html_too_large | chyba | HTML nad 102 000 B |
no_unsubscribe | upozornění | chybí {{unsubscribe}}; Poštárna doplní standardní patičku |
footer_incomplete | upozornění | odhlášení není odkaz nebo chybí jméno odesílatele; doplní se patička |
subject_long, img_without_alt, insecure_image, image_foreign_host, text_image_ratio | upozornění | doporučení |
Zástupné značky
| Značka | Hodnota |
|---|---|
{{df_name}}, {{df_surname}} | křestní jméno, příjmení |
{{df_salution}} | oslovení v 5. pádě („Petře“) |
{{df_emailaddress}} | e-mail příjemce |
{{df_titlesbefore}}, {{df_titlesafter}}, {{df_gender}}, {{df_birthday}}, {{df_nameday}}, {{df_language}}, {{df_company}}, {{df_street}}, {{df_town}}, {{df_postalcode}}, {{df_country}}, {{df_phone}}, {{df_cellphone}}, {{df_notes}} | další pole kontaktu |
{{df_id}}, {{df_created}}, {{df_updated}}, {{df_domain}} | ID kontaktu, založení, poslední změna, doména adresy |
{{cf_<id>}} | vlastní pole podle ID (víc hodnot oddělených čárkou) |
{{cl_sendername}}, {{cl_senderemail}} | jméno a e-mail odesílatele |
{{cl_company}}, {{cl_address}} | firma a adresa odesílajícího e-shopu |
{{unsubscribe}} ({{unsubscribelink}}) | odkaz na odhlášení jedním kliknutím |
{{preferences}} ({{confirmlink}}) | odkaz na nastavení odběru |
{{webversion}} ({{webversionlink}}, {{forwardLink}}) | webová verze e-mailu |
{{coupon_<klíč>}} | nový kód ze zásobníku kupónů s tímto klíčem |
Náhrada prázdné hodnoty: {{df_name|default('zákazníku', true)}}. Text náhrady má 1 až 40 znaků a nesmí obsahovat ' " \ { } < > | % &.
V testovacím e-mailu se dosadí jméno „Test“ a odkazy na odhlášení vedou na ukázkovou stránku, takže test nikoho neodhlásí.
Skripty (Twig)
Obsah smí obsahovat bezpečnou podmnožinu jazyka Twig, stejně jako SmartEmailing: {% if %}, {% elseif %}, {% else %}, {% for %} (i loop), {% set %}, komentáře {# #}, operátory and, or, not, in, ~, ??, ? :, testy (is defined, empty, null, even, odd, divisible by), filtry (abs, capitalize, date, default, first, join, json_encode, keys, last, length, lower, merge, number_format, replace, reverse, round, slice, sort, split, striptags, title, trim, upper, url_encode) a funkce date(), min(), max(). Každá vypsaná hodnota se escapuje, filtr raw není.
Data pro skripty:
| Výraz | Co vrátí |
|---|---|
data.orders(filtr, řazení, limit) | objednávky kontaktu v e-shopu e-mailu (nejvýš 200 nejnovějších); položky items[] |
data.products({'item_id': kód}, řazení, limit) | produkty produktových feedů e-shopu |
data.articles(filtr, řazení, limit) | články článkových feedů (nejvýš 25) |
data.lists(filtr) | seznamy kontaktu a jejich stavy |
data.promoCode('<název zásobníku>') | nový kód kupónu ze zásobníku s tímto názvem pro každý e-mail |
data.promo.assigned('<zásobník>', od, do) | kódy, které kontakt už dostal |
data.terminate('<důvod>') | e-mail tomuto kontaktu neodešle (přeskočí se) |
metadata.order | objednávka, která spustila běh automatizace (jen v e-mailu automatizace) |
metadata.event.attributes | data události, která běh spustila (košík: itemCount, total, currency, shopId; vlastní událost: name a data; návštěva: url, visitType, attributes) |
{% set o = metadata.order %}
{% if o %}
<p>Děkujeme za objednávku {{ o.eshop_code }}.</p>
<ul>{% for item in o.items %}<li>{{ item.name }}</li>{% endfor %}</ul>
{% endif %}
<p>Váš kód: <strong>{{ data.promoCode('Svátek') }}</strong></p>- Kupón:
{{ data.promoCode('Svátek') }}bere název zásobníku,{{coupon_svatek}}jeho klíč (mergeKey). Když zásobník dojde, e-mail neodejde a automatizace zaznamená selhánícustomizationDataboxOutOfPromocodes. - Skript, který nejde spustit, zastaví e-mail (
failed); kontrola obsahu ho najde dřív jakoscript_error. - Nepodporováno: seznam položek košíku v e-mailu (v datech košíku je jen počet kusů a součet), obecné feedy (
data.generic.itemsvrací prázdný seznam).
Testovací e-mail
- Jde jen na testovací adresy firmy (
GET /test-recipients); jiná adresa = 400validation/to. POST /campaigns/{id}/tests{"to"},POST /templates/{id}/tests{"shopId", "to"}. Předmět dostane předponu[TEST], nic se neměří.- Nejvýš 10 testů jedné kampaně nebo šablony za 24 hodin (429
rate_limited/test).
curl -sS -X POST "https://www.postarna.cz/api/v1/tenants/$TENANT/campaigns/151/test" \
-H "Authorization: Bearer $POSTARNA_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @- <<'JSON'
{
"to": "test@example.cz"
}
JSON{
"to": "test@example.cz",
"sentAt": "2026-10-01T08:00:00.000Z"
}Patičky, odhlašovací stránky a další obsah
- Patičky (
/footers) a odhlašovací stránky (/unsubscribe-pages) mají výchozí položku firmy; šablona a uzel automatizace mohou mít vlastní. - Šablony skriptů (
/script-templates), uložené prvky editoru (/editor-elements), správce souborů (/files,/file-folders), landing pages, dotazníky a šablony SMS mají vlastní skupiny v referenci.