Skip to content

Releases: faborsky/sklik-ppc-app

v1.9.0 — Výpisy vrací kompletní data (konec tichého usekávání) 📄

Choose a tag to compare

@faborsky faborsky released this 20 Aug 12:14

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: campaigns bralo z API jen prvních 100 kampaní (limit: 100, offset: 0)
    a --status filtroval až nad touhle useknutou stovkou — takže --status active
    a --status suspend dohromady 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ýpisechgroups, ads, banners a banner-download
    po 500 řádcích, keywords a negatives po 5000. Nově se všechny stránkují až do konce.
  • FIX: campaign-update hledal 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. readReport ví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ý
    --limit funguje dál jako strop.
  • Jak to funguje: stránkování je centrálně v enginu — api._fetch_all() pro *.list
    a reports._read_report_rows() pro reporty; velikost stránky se bere z api.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-id filtrovalo až nad useknutým reportem
    úplně stejná past jako u campaigns --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 --limit ořezává až výsledek
    (lidský výstup pak píše showing first N of M).
  • Odolnost proti 413: retargeting-attached posí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 readReport jsou offset/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 v docs/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 🎯

Choose a tag to compare

@faborsky faborsky released this 20 Aug 10:25

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: --regions posí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ři campaign-create, ani při campaign-update.
  • FIX: --device-bids posílalo desetinná čísla. Hodnoty se parsovaly přes float(),
    takže i 0:-30:-30:-100 odešlo jako 0.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-json byl 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, null rozvrh smaže, a špatný počet dní/hodin odchytí lokálně
    (dřív z toho bylo 406 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) i nil (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() jako int, ostatní
    číselné přepínače jsou type=int. Ověřen i tvar --conditions-json
    (retargeting-create), který dosud nikde nebyl popsaný.
  • Dokumentace: docs/api-notes.md má 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, že campaigns.check
    ověří payload zadarmo
    — stejné vstupy jako create/update, žádný zápis, jedno volání.
    Do CLAUDE.md přibylo pravidlo kontrolovat tvar payloadu při každé změně zápisu.

v1.8.0 — Win rate, granularita statistik a oprava zobrazení CTR

Choose a tag to compare

@faborsky faborsky released this 11 Aug 11:03
  • NOVÉ: winRate ve 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,
    byly ish/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} u campaign-stats,
    group-stats, keyword-stats a ad-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-total granularity 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ýpisu campaigns — sloupec Rotation
    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í ctr jako podíl
    (0,0073), CLI ho tisklo jako procento → CTR: 0.01% místo 0.73% v campaign-stats,
    group-stats, keyword-stats, ad-stats a search-queries. pulse a account
    si CTR počítají samy, ty postižené nebyly. --json výstup se nemění (ctr
    zůstává podílem) — na jeho tvaru stojí navazující automatizace.
  • FIX: avgCpt se nepřevádělo z haléřů na Kč jako ostatní peněžní sloupce.
  • FIX: sitelinks padalo na TypeError, když měl odkaz prázdnou URL — API vrací url: null
    a .get("url", "") proti None nechrá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; banners a placements už ošetřené byly.
  • Interně: STAT_COLUMNS nahrazen funkcí stat_columns(entity), protože sloupce
    povolené pro jednu entitu shodí readReport u 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 v docs/api-notes.md.

v1.7.2 — Oprava jednotek hodnoty konverzí (100×) 🐛

Choose a tag to compare

@faborsky faborsky released this 21 Jul 05:41
  • FIX: conversionValue ze 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 --json výstupu campaign-stats, group-stats, keyword-stats, ad-stats, search-queries a v pulse navíc 100× nadhodnocené PNO. Ověřeno živě proti sloupci pno, 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 conversionPrice z 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 📖

Choose a tag to compare

@faborsky faborsky released this 21 Jul 05:41
  • groups nově vrací maxUserDailyImpressions (frekvenční strop sestavy — max zobrazení na uživatele za den) v --json i tabulce (sloupec Freq/day). Dosud šla hodnota jen nastavit, ne přečíst — čtecí sloupec v API je plurál maxUserDailyImpressions (setter je singulár). Čistě aditivní.

Plný changelog: CHANGELOG.md

v1.7.0 — Vizuální podpis + čitelný help 🎨

Choose a tag to compare

@faborsky faborsky released this 19 Jul 16:50
  • 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. Respektuje NO_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

Choose a tag to compare

@faborsky faborsky released this 19 Jul 06:54

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 namespace retargeting.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-restore s 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.
  • pulse hlídá validitu dat: přes stats.status zkontroluje, ž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; sitelinks filtruje 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.