@koda-sl/baker-cli 0.287.0-dev.93be96120 → 0.290.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1256,10 +1256,15 @@ baker analytics tracking # do the ad URLs carry the campaign, a
1256
1256
  baker analytics tracking --platform meta # the same for one platform, read from their own ad account
1257
1257
  baker analytics map --platform google --set kw=keyword # name a parameter, seen or not yet
1258
1258
  baker analytics map --platform google --remove kw # take that answer back
1259
- baker analytics conversions # what counts as a conversion, and what each one produced
1259
+ baker analytics conversions # what counts, what each produced, and which Forms count nothing
1260
1260
  baker analytics conversions --candidates # everything these pages do, and which of it is counted
1261
+ baker analytics conversions --flow contact # one Form's endings as event keys, traffic or not
1261
1262
  baker analytics conversions --event page:request_demo --name "Demo requested"
1263
+ baker analytics conversions --event page:a --event submit:b --name "Lead" # both, as one number
1264
+ baker analytics conversions --event page:a --count-mode every_time # re-mode, keeping its name
1265
+ baker analytics conversions --rename "Lead form" --to "Lead" # merge two into one row
1262
1266
  baker analytics conversions --remove page:request_demo
1267
+ baker analytics conversions --remove-name "Lead"
1263
1268
  baker analytics delivery --page 2 # the next page of a long list
1264
1269
  baker analytics submissions --flow contact # every attempt at a Form, delivered or not
1265
1270
  ```
@@ -1274,7 +1279,11 @@ Shared flags: `--days <n>` (default 30) or `--start-date` / `--end-date` (`YYYY-
1274
1279
 
1275
1280
  **Paging the list reports.** `people`, `submissions` and `delivery` are lists of individual things rather than breakdowns — `delivery` and `submissions` are the ones the CLI exposes, `people` backs the People section of the dashboard's landing Analytics screen over the same wire — and only they take `--page <n>` (1-based) and `--page-size <n>` (up to 200, default 50). The response carries `pageInfo` with `hasMore` — when it is true there **are** more rows, so a total must never be reported from one page. Pass neither flag and a list comes back at the size it always did.
1276
1281
 
1277
- **A conversion is a company-level named event, not a property of a Form.** `baker analytics conversions` is the only place "what counts" is decided, and an empty `definitions` list means every conversion number in every other report is zero — not because nobody converted, but because nothing is named as an outcome and Baker never guesses which event is the point of a page. `--candidates` lists every event these pages actually produced — each Form step and trigger, every `data-baker-*` event, every outbound destination — with volume and whether it is already counted; that list is where an event key comes from, so never invent one. `--event <key> --name "Booked a call"` starts counting it **immediately and retroactively**: the whole stored history is rescored, so naming the right event today also fixes last month. Nothing here is staged and publishing is not involved. Two events given the same `--name` become one row and one number, which is how a call booked on three different Forms reads as one outcome. `--count-mode every_time` is for the outcomes people genuinely repeat (a guide downloaded twice is two downloads); the default counts once per visit. One outcome per call — repeating `--event` is refused rather than silently keeping the last one.
1282
+ **A conversion is a company-level named event, not a property of a Form.** `baker analytics conversions` is the only place "what counts" is decided, and an empty `definitions` list means every conversion number in every other report is zero — not because nobody converted, but because nothing is named as an outcome and Baker never guesses which event is the point of a page. `--candidates` lists every event these pages actually produced — each Form step and trigger, every `data-baker-*` event, every outbound destination — with volume and whether it is already counted; that list is where an event key comes from, so never invent one. `--event <key> --name "Booked a call"` starts counting it **immediately and retroactively**: the whole stored history is rescored, so naming the right event today also fixes last month. Nothing here is staged and publishing is not involved. Two events given the same `--name` become one row and one number, which is how a call booked on three different Forms reads as one outcome. `--count-mode every_time` is for the outcomes people genuinely repeat (a guide downloaded twice is two downloads); the default counts once per visit.
1283
+
1284
+ **The name is the grouping, so the CLI defends it.** Repeat `--event` to count several events under one `--name` in a single call; `--rename "<old>" --to "<new>"` renames every event under an outcome, and renaming *onto* a name that already exists **merges** them into one row and one number — the fix for a company whose Forms each invented their own word for the same thing. `--remove-name` drops an outcome entirely, `--remove` a single event key. A name that differs from one already counted only by case, accent, punctuation or a plural is **refused**: Baker groups by exact name, so "Booked a Call" beside "Booked a call" is a number split in half with both halves plausible. Every answer leads with the names already in use, and a company that has named nothing gets a standard set to start from — after which the rule is reuse, in that company's own language.
1285
+
1286
+ **`--flow <slug>` reads it from the Form's side**, listing that Form's endings already spelled as event keys with the name each is counted under, built from the Form's own file so it works before a single visitor arrives. With no `--flow`, the answer carries `flows[]` — every Form in the workspace with the step that counts for it, or nothing — which exists nowhere else: on every other report a Form that counts nothing looks exactly like a Form nobody converts on. The list of definitions is read from the store rather than from the reporting mirror, so an outcome named a second ago is in the reply that named it.
1278
1287
 
1279
1288
  **Campaign parameters are per platform, and so are the numbers.** `baker analytics ads` returns `adPlatformTraffic` (visits, conversions and *tagged* visits for each of the nine platforms), `adParams` for the platform in `--platform` only, and `adParamsUnattributed` for names arriving on visits with no click id and no recognisable source. Read `adPlatformTraffic` first: a platform with visits and zero tagged visits has untagged ad URLs, and no mapping can fix that from Baker's side. `baker analytics map` needs `--platform` for any change, accepts a parameter name **nobody has sent yet** — which is how a tracking template is configured before its campaign runs — and takes an answer back with `--remove`. `--set <name>=ignore` says a parameter is not campaign information at all, so Baker stops storing it and stops listing it.
1280
1289
 
@@ -1315,25 +1324,33 @@ Two versions of one landing page, split 50/50 at the edge, read on one of the co
1315
1324
 
1316
1325
  ```bash
1317
1326
  baker experiment plan --landing oferta --variant oferta--1 # FIRST — can this page settle the question at all?
1318
- baker experiment plan --landing oferta --variant oferta--1 --goal "Booked a call"
1327
+ baker experiment plan --landing oferta --variant oferta--1 --goal submit:book-a-call
1319
1328
  baker experiment start --landing oferta --variant oferta--1 --because "60% of visitors never scroll past the hero" --change "put the price in the headline"
1329
+ baker experiment update --id temp_exp_1 --goal submit:book-a-call # a staged test can still change what it measures
1330
+ baker experiment update --id a3f91c2b --because "…" # a live one can only change its wording
1320
1331
  baker experiment status # the verdict on every test
1321
- baker experiment status --id a3f91c2b --full # one test, with the posteriors behind it
1332
+ baker experiment status --id a3f91c2b --full # one test, with the confidence and posteriors behind it
1333
+ baker experiment history --landing oferta # every finished test on a page: claim, numbers, decision, learning
1322
1334
  baker experiment pause --id a3f91c2b # everyone sees the original for now
1323
1335
  baker experiment resume --id a3f91c2b # the split picks up with the same sides
1324
- baker experiment finish --id a3f91c2b --keep variant # end it now; say which version stays
1336
+ baker experiment finish --id a3f91c2b --keep variant --learning "…" # end it now; say which version stays and what it taught
1337
+ baker experiment cancel --id a3f91c2b # call it off: staged → gone, live → ended, original kept
1325
1338
  baker experiment fold # make the page's own content the version that was kept
1326
1339
  ```
1327
1340
 
1328
- **A page has variants. A variant is never a page.** The variant is a real built folder at `src/pages/oferta--1/`, so it gets every quality gate a page gets — which matters, because it is about to be shown to half the client's visitors. What it does not get is a public address: it is absent from the Landings list and the sitemap, carries `noindex`, and `/oferta--1/` returns **404** at the edge. Both versions answer at `/oferta/`. Assignment happens while the HTML is served, so there is no flicker and nothing for an ad blocker to suppress, and the split is a path rewrite and never a redirect. To look at one side deliberately, `/oferta/?_bkr_preview=a` and `?_bkr_preview=b` serve it exactly, with no assignment and no cookie.
1341
+ **A page has variants. A variant is never a page.** The variant is a real built folder at `src/pages/oferta--1/`, so it gets every quality gate a page gets — which matters, because it is about to be shown to half the client's visitors. What it does not get is a public address: it is absent from the Landings list and the sitemap, names the page's URL as its canonical, and `/oferta--1/` returns **404** at the edge. It is as indexable as the page it is a version of, deliberately — half the crawls of `/oferta/` are served the variant, so a `noindex` on it is a `noindex` on the live page. Both versions answer at `/oferta/`. Assignment happens while the HTML is served, so there is no flicker and nothing for an ad blocker to suppress, and the split is a path rewrite and never a redirect. To look at one side deliberately, `/oferta/?_bkr_preview=a` and `?_bkr_preview=b` serve it exactly, with no assignment and no cookie.
1342
+
1343
+ **The goal is one event, named by its key.** `--goal submit:book-a-call` — the same vocabulary the event stream uses (`form:<flow>:<node>:<trigger>`, `submit:<flow>`, `page:<name>`, `exit:<host>`), and `baker analytics conversions --candidates` lists the keys these pages produce. Not a conversion *name*, which groups several keys: a variant that swaps the page's Form for a shorter one converts on a different key, and a name would either count both endings as one outcome or count the new version as never converting at all — `--variant-goal` gives the new version its own event when it has one. The goal is fixed for the life of the test and the verdict is read on it alone. Every other conversion the company counts comes back under `secondary` on every result, with the same interval and a one-word reading, and decides nothing. A conversion counts for a visitor wherever it happens after they were shown a version — on the page, on another page, in a delivered lead, or in a deal the CRM posted a week later by email.
1329
1344
 
1330
- **The goal is one of the company's conversions, by name.** `--goal "Booked a call"` spelled as the Conversions screen spells it. It is fixed for the life of the test and the verdict is read on it alone. Every other conversion the company counts comes back under `secondary` on every result, with the same interval and a one-word reading, and decides nothing. A conversion counts for a visitor wherever it happens after they were shown a versionon the page, on another page, in a delivered lead, or in a deal the CRM posted a week later by email.
1345
+ **Nothing ends a test on its own.** `status` returns a verdict; `finish --keep original|variant` is the decision, and it takes effect within seconds with nothing to publish. Ending a `keep_running` test records `inconclusive`. Going against the verdict is allowed and recorded. `pause` and `resume` switch the split off and on without losing the test; `cancel` is `finish --keep original` for a live test and takes a staged one back off the session. `update` changes what a test *says* `--because`, `--change`, `--evidence` (repeatable, `source:what it showed`, optionally `|link`) at any time, writes down what a finished one taught (`--learning`), and changes what it *measures* `--goal`, `--lift`, `--expect` only while it is still staged.
1331
1346
 
1332
- **Nothing ends a test on its own.** `status` returns a verdict; `finish --keep original|variant` is the decision, and it takes effect within seconds with nothing to publish. Ending a `keep_running` test records `inconclusive`. Going against the verdict is allowed and recorded. `pause` and `resume` switch the split off and on without losing the test.
1347
+ **A finished test is a record.** Its counts are frozen when it ends, so it reads the same next year as it did that day; its `learning` is what it taught, in a person's words. `history` returns every finished test the claim, what was different, the numbers with their interval and confidence, what was kept and whether that went against the numbers, whether the belief held, and the learning — and `plan` returns the same entries as `pastTests` for the page it sizes, so a hypothesis is chosen against the page's record rather than in ignorance of it.
1348
+
1349
+ **The confidence is anytime-valid.** `--full` carries `evidence.confidence`, how sure the numbers are that the two versions differ at all, read off the same construction as the verdict — so it holds however often it is read, and a winner is called exactly when it crosses 95%. Beside it, `probabilityVariantBetter` is the Bayesian chance the new variant is the better one, which is for printing and never for deciding.
1333
1350
 
1334
1351
  **Finishing with the variant takes two beats, and `fold` is the second.** `finish --keep variant` records which version is live and the edge serves it to everyone at once. `baker experiment fold` moves that version into the page's own folder, archives the one that lost as a self-contained snapshot under `src/_variants/<page id>/<n>/`, and deletes the variant folder. Until it runs, the page is served by a rewrite and cannot be tested again. Run `fold` with no arguments after any test ends, then publish; Baker drops the rewrite by itself once the new pages are live.
1335
1352
 
1336
- **`plan` before building anything.** At a 3% conversion rate a +20% lift needs roughly 14,000 visitors *per variant*; most landing pages will never get there, and `plan` refuses rather than letting a test run for three weeks and report a conclusion made on noise. It also lists what this page's visitors actually went on to do, and what a 14, 28, 56 or 90-day window could settle. `--lift` sets the smallest lift worth detecting (default `0.2`) — halving it roughly quadruples the traffic needed.
1353
+ **`plan` before building anything.** At a 3% conversion rate a +20% lift needs roughly 14,000 visitors *per variant*; `plan` says how long that is at this page's traffic, lists what this page's visitors actually went on to do, and what a 14, 28, 56 or 90-day window could settle. The duration is a guide and never a finish line — the test ends when the numbers are clear, and a page with no traffic yet still runs, sized on a stand-in that `warning` names (`--baseline 0.05` states the rate to expect). What `plan` refuses is what cannot be measured: no conversion defined, or a goal the page has demonstrably never produced. `--lift` sets the smallest lift worth detecting (default `0.2`) — halving it roughly quadruples the traffic needed.
1337
1354
 
1338
1355
  ### Google Analytics 4 (`baker ga4`)
1339
1356
 
@@ -5818,9 +5835,12 @@ Creates a new **version of a page** for an A/B test. It **imports the page's sec
5818
5835
 
5819
5836
  ```bash
5820
5837
  baker landing variant oferta --fork Hero.astro
5821
- baker landing variant oferta --fork Hero.astro,Proof.astro --because "60% of visitors never scroll past the hero" --change "put the price in the headline"
5838
+ baker landing variant oferta --fork Hero.astro --fork Proof.astro --because "60% of visitors never scroll past the hero" --change "put the price in the headline"
5839
+ baker landing variant oferta --fork Hero.astro,Proof.astro --because "…" --change "…"
5822
5840
  ```
5823
5841
 
5842
+ - **`--fork` takes several components, repeated or comma-separated.** Both forms keep every name.
5843
+
5824
5844
  - **You do not choose the slug.** It is `<page>--<n>`, numbered per page and never reused — so it cannot collide with an archived version, and it cannot merge with an older variant's analytics history. `--` is also what every tool decides by: which analytics id the page stamps, whether the sitemap lists it, and whether the edge answers the URL. It replaced a `<page>-b` convention that nine live pages across the fleet would have been misread by.
5825
5845
 
5826
5846
  - **Sharing, not copying, is what keeps the test honest.** A duplicated page drifts from its control on every later edit — a price, a typo, a new testimonial — and the test then reports that drift plus the hypothesis as one result. A shared section is one file, so an edit reaches both arms at once. Baker follows the sharing too: both pages redeploy together, and both are re-critiqued when a shared section changes.
@@ -16,9 +16,9 @@ import {
16
16
  shouldEscalate
17
17
  } from "./chunk-DZUVUGEP.js";
18
18
 
19
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/509a695c9237c6e3727f1f1f99169917f329e3ff3f7877be290b684e24bf153d/node_modules/safe-stable-stringify/index.js
19
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js
20
20
  var require_safe_stable_stringify = __commonJS({
21
- "../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/509a695c9237c6e3727f1f1f99169917f329e3ff3f7877be290b684e24bf153d/node_modules/safe-stable-stringify/index.js"(exports, module) {
21
+ "../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/index.js"(exports, module) {
22
22
  "use strict";
23
23
  var { hasOwnProperty } = Object.prototype;
24
24
  var stringify = configure2();
@@ -1092,7 +1092,7 @@ function resolveAdaptFormats(params) {
1092
1092
  return params.formats ?? [];
1093
1093
  }
1094
1094
 
1095
- // ../../.pnpm-store/v10/links/@/safe-stable-stringify/2.5.0/509a695c9237c6e3727f1f1f99169917f329e3ff3f7877be290b684e24bf153d/node_modules/safe-stable-stringify/esm/wrapper.js
1095
+ // ../../node_modules/.pnpm/safe-stable-stringify@2.5.0/node_modules/safe-stable-stringify/esm/wrapper.js
1096
1096
  var import__ = __toESM(require_safe_stable_stringify(), 1);
1097
1097
  var configure = import__.default.configure;
1098
1098
  var wrapper_default = import__.default;
@@ -9153,4 +9153,4 @@ export {
9153
9153
  defaultRegistry,
9154
9154
  createEngineFromEnv
9155
9155
  };
9156
- //# sourceMappingURL=chunk-LN5O53BG.js.map
9156
+ //# sourceMappingURL=chunk-V7BIRLPU.js.map