Releases: faborsky/sklik-ppc-app
Release list
v1.9.0 — Výpisy vrací kompletní data (konec tichého usekávání) 📄
Appka četla z API vždycky jen první stránku a tvářila se, že je to celý účet.
Nahlásil to student kurzu AI First na výpisu kampaní; kontrola ukázala, že stejný
strop měl každý výpis v appce. Nejde o kosmetiku — na Jindrově vlastním účtu měl
ads 521 inzerátů a vypisoval jich 500.
- FIX:
campaignsbralo z API jen prvních 100 kampaní (limit: 100, offset: 0)
a--statusfiltroval až nad touhle useknutou stovkou — takže--status active
a--status suspenddohromady nikdy nedaly víc než 100 řádků. Účet se 130 kampaněmi
o 30 z nich tiše přišel; API na to neupozorní (v odpovědi není celkový počet). - FIX: stejný strop v dalších výpisech —
groups,ads,bannersabanner-download
po 500 řádcích,keywordsanegativespo 5000. Nově se všechny stránkují až do konce. - FIX:
campaign-updatehledal typ kampaně v seznamu prvních 100 kampaní — u většího
účtu tedy úprava kampaně #101 a dál skončila hláškou „Campaign not found", i když
kampaň existovala. Teď se ptá přímo na to jedno ID (levnější a správné). - FIX: statistiky se usekávaly na 5000 řádcích.
readReportvíc nežstatsDataLimit
nevrátí a CLI si o zbytek neřeklo — u velkých účtů (keyword-stats,search-queries,
výpisy umístění) prostě chyběl konec dat. Report se teď dočte celý, uživatelský
--limitfunguje dál jako strop. - Jak to funguje: stránkování je centrálně v enginu —
api._fetch_all()pro*.list
areports._read_report_rows()pro reporty; velikost stránky se bere zapi.limits
(statsDataLimit, obvykle 5000), takže se sama přizpůsobí účtu. Runaway pojistka na
200 000 řádků hlásí useknutí na stderr — appka už nikdy nevrátí neúplný seznam mlčky. - FIX:
search-queries --campaign-id/--group-idfiltrovalo až nad useknutým reportem —
úplně stejná past jako ucampaigns --status: přečetlo se prvních--limitřádků z celého
účtu a teprve na nich se hledala daná kampaň. Na testovacím účtu tak jedna kampaň místo
124 dotazů ukázala 6. Nově se při filtru čte celý report a--limitořezává až výsledek
(lidský výstup pak píšeshowing first N of M). - Odolnost proti 413:
retargeting-attachedposílal ID všech sestav v jednom poli;
na velkém účtu by přetekl per-call limit. Teď se dotazuje po dávkách. - Zjištěno při testování stránkování reportů: v
readReportjsouoffset/limit/totalCount
v jednotkách entit, ne vrácených řádků. U reportu vyhledávacích dotazů (queries) to není
totéž — vrací všechny dotazy klíčových slov na dané stránce, takže žádost o 5 klíčových slov
vrátí 6 řádků a 138 klíčových slov dá 127 řádků dotazů. Stránkovat podle počtu řádků by data
duplikovalo; appka proto posouvá offset o velikost stránky. Popsáno vdocs/api-notes.md. - Cena: velký účet znamená víc requestů na jeden výpis (20 000 klíčových slov = 4 volání).
Request-budget to hlídá jako dřív; při skriptování nevoláním výpisy zbytečně dokola. - Kontrola zbytku appky: metody, které stránkovací parametry vůbec nemají
(conversions.list,sitelinks.list,retargeting.lists.list,sharedbudgets.list,
images.constraints.list), vrací všechno v jednom volání — tam problém není.
Ověřeno živě: offsety se nepřekrývají a stránkovaný i nestránkovaný běh vrací
identická data (kampaně, klíčová slova i report po 2/5/7 řádcích na stránku).
v1.8.1 — Cílení kampaní opraveno: geo, modifikátory zařízení, rozvrh 🎯
Celá trojice přepínačů pro cílení kampaní posílala do API špatné datové tvary, takže
žádný z nich nikdy nefungoval — vždycky skončil chybou 400 Bad arguments. Nahlásil
student kurzu AI First (--regions); zbylé dvě chyby vyplavala kontrola zbytku téhle
rodiny přepínačů proti dokumentaci API a živé ověření přes campaigns.check.
- FIX:
--regionsposílalo holá čísla místo structů. API čeká
[{"predefinedId": 100001}, …], CLI posílalo[100001]→400 Parameter campaigns[0].regions[0] must be struct, not int. Geo cílení tedy nešlo nastavit
vůbec — ani přicampaign-create, ani přicampaign-update. - FIX:
--device-bidsposílalo desetinná čísla. Hodnoty se parsovaly přesfloat(),
takže i0:-30:-30:-100odešlo jako0.0/-30.0/…→400 … devicesPriceRatio.desktop must be int, not double. Nově jdou jako celá čísla; desetinný vstup (-30.5) CLI
odmítne s vysvětlením místo záhadné chyby z API. - FIX:
--schedule-jsonbyl dokumentovaný v tvaru, který API odmítá. README i nápověda
ukazovaly{"daySchedule":[{"value":[…]}, …]}— což je tvar, v jakém API rozvrh vrací,
ne v jakém ho přijímá (400 … schedule must be array or nil, not struct). Zápis chce
7 polí po 24 hodnotách 0–100 ([[0,…,100,…], …×7], týden od pondělí). CLI teď přijme
oba tvary a převede,nullrozvrh smaže, a špatný počet dní/hodin odchytí lokálně
(dřív z toho bylo406 campaign_invalid_schedule_size). - Zrušení geo cílení přes API nejde — a
--regions ""to dřív tiše slibovalo. API
odmítá prázdné pole (400 Array cannot be empty) inil(400 … regions cannot be nil),
takže regiony jde odebrat jedině ve webovém rozhraní Skliku. CLI to teď řekne rovnou
místo odeslání payloadu, který vždycky spadne. Nastavení regionů navíc nahrazuje
celou sadu, což je nově v dokumentaci. - Kontrola zbytku appky: všechny ostatní zapisované payloady byly porovnány s oficiální
dokumentací API metod (structy vs. skaláry, int vs. double). Další chybu stejného druhu
nenašla — peněžní hodnoty jdou do API vždy přes_czk_to_halere()jakoint, ostatní
číselné přepínače jsoutype=int. Ověřen i tvar--conditions-json
(retargeting-create), který dosud nikde nebyl popsaný. - Dokumentace:
docs/api-notes.mdmá nově u kampaňového cílení explicitně zápisový vs.
čtecí tvar všech tří polí (liší se u regionů i rozvrhu) a poznámku, žecampaigns.check
ověří payload zadarmo — stejné vstupy jako create/update, žádný zápis, jedno volání.
DoCLAUDE.mdpřibylo pravidlo kontrolovat tvar payloadu při každé změně zápisu.
v1.8.0 — Win rate, granularita statistik a oprava zobrazení CTR
- NOVÉ:
winRateve statistikách sestav (group-stats) — podíl vyhraných aukcí.
Do teď nebyl v CLI vůbec dostupný, přestože ho API vrací; jediné, co se dalo číst,
bylyish/ishSum/missImpressions, které jsou u obsahových kampaní konstantní
a nenesou informaci. Existuje jen na sestavách — kampaně, klíčová slova ani
inzeráty ekvivalent nemají. - NOVÉ:
--granularity {total,daily,weekly,monthly,quarterly,yearly}ucampaign-stats,
group-stats,keyword-statsaad-stats. Dvoukrokový report to uměl už dřív, ale
CLI to nevystavovalo — denní řadu šlo dosud získat jen voláním po jednom dni.
U ne-totalgranularity přibude v lidském výstupu datum období. - NOVÉ statistické sloupce tam, kde je API pro danou entitu zná:
exhaustedBudgetShare
(podíl dne s vyčerpaným rozpočtem — jemnější než binárníexhaustedBudget),
impressionMoney/clickMoney(rozpad útraty),avgCpt,underForestThreshold,
stoppedBySchedule. - NOVÉ:
adSelection(rotace reklam) ve výpisucampaigns— sloupecRotation
v lidském výstupu a klíč v--json. Nastavit ji šlo dosud přes--ad-selection,
ale přečíst zpátky ne. - FIX: CTR se v lidském výstupu tisklo 100× menší. API vrací
ctrjako podíl
(0,0073), CLI ho tisklo jako procento →CTR: 0.01%místo0.73%vcampaign-stats,
group-stats,keyword-stats,ad-statsasearch-queries.pulseaaccount
si CTR počítají samy, ty postižené nebyly.--jsonvýstup se nemění (ctr
zůstává podílem) — na jeho tvaru stojí navazující automatizace. - FIX:
avgCptse nepřevádělo z haléřů na Kč jako ostatní peněžní sloupce. - FIX:
sitelinkspadalo naTypeError, když měl odkaz prázdnou URL — API vracíurl: null
a.get("url", "")protiNonenechrání (klíč existuje, default se nepoužije). Nalezeno při
regresním testu této verze.⚠️ Stejný vzorec je i v dalších výpisech (campaigns,groups,
keywords,retargeting,conversions,account) — tam zatím pád nikdo nenahlásil, takže
zůstávají beze změny;bannersaplacementsuž ošetřené byly. - Interně:
STAT_COLUMNSnahrazen funkcístat_columns(entity), protože sloupce
povolené pro jednu entitu shodíreadReportu jiné (400 Bad arguments). Původní
název zůstává kvůli zpětné kompatibilitě. Kompletní mapa sloupců podle entit +
poznámka, že kampaňová frekvence zobrazení v API vůbec neexistuje (a že
sestavový cap přebíjí kampaňový), je vdocs/api-notes.md.
v1.7.2 — Oprava jednotek hodnoty konverzí (100×) 🐛
- FIX:
conversionValueze statistik se už nedělí stem. API vrací tento report sloupec přímo v Kč (hodnota posílaná konverzním kódem), na rozdíl od ostatních peněžních sloupců v haléřích. CLI ho převádělo jako haléře → 100× podhodnocená hodnota konverzí v--jsonvýstupucampaign-stats,group-stats,keyword-stats,ad-stats,search-queriesa vpulsenavíc 100× nadhodnocené PNO. Ověřeno živě proti sloupcipno, který počítá samo API. Nahlásil uživatel — díky! - Audit všech ostatních peněžních míst (bidy, rozpočty, kredit, suggest CPC, konverzní definice) proti surovým odpovědím API: jednotky správně, beze změn.
- Odstraněn mrtvý sloupec
conversionPricez převodní tabulky (API žádný takový report sloupec nemá). - Quirk zdokumentován v docs/api-notes.md.
Plný changelog: CHANGELOG.md
v1.7.1 — Čtení frekvenčního stropu sestavy 📖
groupsnově vracímaxUserDailyImpressions(frekvenční strop sestavy — max zobrazení na uživatele za den) v--jsoni tabulce (sloupecFreq/day). Dosud šla hodnota jen nastavit, ne přečíst — čtecí sloupec v API je plurálmaxUserDailyImpressions(setter je singulár). Čistě aditivní.
Plný changelog: CHANGELOG.md
v1.7.0 — Vizuální podpis + čitelný help 🎨
- ASCII banner s barvami („SKLIK" v seznamácké červené + verze, tagline, byline) — jen pro lidi v terminálu (TTY bez
--json); pipe a agentní tool-cally dostávají čistý výstup. RespektujeNO_COLOR. - Seskupený
--help: 88 příkazů po doménách místo jednoho plochého seznamu; přehled se generuje ze skutečně registrovaných subparserů. - Doplněný LICENSE (MIT) — README licenci deklarovalo, soubor v repu chyběl.
Plný changelog: CHANGELOG.md
v1.6.0 — Kompletní pokrytí obsahovky + záchranná brzda
Největší rozšíření od začátku: 34 nových příkazů (54 → 88), postavené podle gap analýzy oficiální DRAK dokumentace. Všechno otestované živě na sandbox kampani (vytvořena → proklikána → smazána).
- Remarketing konečně celý přes API:
retargeting-attach/retargeting-detach/retargeting-attached. Napojení publika na sestavu bylo dosud považované za „jen přes web UI" — ukázalo se, že žije v samostatném namespaceretargeting.group.lists.*. Celý workflow (vytvoř publikum → napoj na sestavu → zkontroluj) teď jde bez klikání. - Negativní retargeting:
retargeting-exclude/retargeting-excluded/retargeting-exclude-remove— vyloučení publika z kampaně nebo sestavy (typicky „vyluč zákazníky z akviziční kampaně"); na rozdíl od napojení funguje i na search kampaních. - Vylučující umístění:
placement-exclude/placements-excluded/placement-exclude-remove/placement-exclude-restore— vyloučení webů z obsahových sestav (patterns.negative.*), základ optimalizace obsahovky. Pozor na dva quirky (API nevrací text vzoru; smazané vyloučení blokuje re-create → restore) — zdokumentováno v api-notes. - Cílení na zájmy / témata / úmysly:
targeting-categories/targeting/targeting-add/targeting-exclude/targeting-remove/targeting-restores jednotným--type interest/theme/intend— tři dosud nedostupné dimenze cílení obsahové sítě, včetně vyloučení a CPC/CPT na kategorii. Výpis joinuje názvy kategorií z číselníku. - Sitelinky dotažené:
sitelink-update,sitelink-assign(kampaň i sestava; nahrazuje celou sadu),sitelinks-assigned. Dosud šly sitelinky jen vytvořit „do vzduchu" — teď jde celý životní cyklus. Přejmenování vytváří nové ID (server remove+create) — CLI ho vrací. - Sdílené rozpočty:
budgets/budget-create/budget-update/budget-remove— jeden denní rozpočet pro víc kampaní; přiřazení kampaní se řídí na rozpočtu. Quirk: částky v Kč, ne haléřích (jediný namespace bez konverze). *-restore(undelete) pro kampaně, sestavy, klíčová slova, inzeráty a bannery — záchranná brzda k--confirm; omylem smazané jde vrátit.keyword-set— deklarativní nastavení slov sestavy (upsert;--remove-others= plná synchronizace podle seznamu).banner-update— status/název/URL banneru bez remove+create.pulsehlídá validitu dat: přesstats.statuszkontroluje, že statistiky za okno jsou kompletní, a když ne (dnešek bývá „preparing"), přidá varování — konec srovnávání s částečnými čísly.credit— zůstatek peněženky (i spravovaných účtů).regions— číselník ID pro--regions.autotagging/autotagging-update— správa UTM konfigurace.- Robustnost: ne-JSON odpověď API (neznámá metoda, výpadek) už neshodí CLI tracebackem, ale vrátí strukturovanou chybu;
sitelinksfiltruje soft-smazané záznamy. - Tooling:
scripts/check_docs_consistency.py— mechanická kontrola CLI ↔ README ↔ CLAUDE.md ↔ skill (parita příkazů, počty, verze, fantomové příkazy). Spouštět před releasem.