@analitikisler/ai-tag-debugger 0.9.0 → 0.11.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.11.0 (2026-10-16)
4
+
5
+ - Every saved run is compared with the site's previous run. The report opens with a "Changed since last run" section (`2 events fixed, 1 new problem`) that lists what was fixed and what is new, by plan coverage when both runs used `--against` and by health findings otherwise. The first run says there is nothing to compare yet. No new flag; the result is also in `capture.json` under `changes`.
6
+ - A plain sentence can be a request: `aitd "check my GA tags"`. The sentence becomes a fixed command through the AI provider, or a keyword matcher when no key is set. aitd prints the command and asks before running it; `-y` skips the question. An unclear sentence gets one short question back. A sentence that names no journey, goal or plan asks what to test, and suggests the site's latest plan when it has one.
7
+ - `aitd plan --topic <name>` limits a plan to one kind of event: `custom-events`, `ecommerce`, `forms` or `consent`. Sentences such as "what custom events does my site need" use it.
8
+ - The MCP server has a `make_plan` tool that drafts a tracking plan for a site, with an optional topic. Chat apps use it when a user asks what a site should track, and `run_audit` or `finish_audit` checks the audit against the plan.
9
+
10
+ ## 0.10.0 (2026-10-16)
11
+
12
+ - Plan, then audit. `aitd plan --site <url>` drafts a measurement plan in its own folder, `aitd/<domain>/plans/<id>/`: the events a site should send, with a description, the page and element that trigger each one, its parameters (custom ones marked) with example values, and suggested user properties. Events the site already sends are marked `seen`. It browses one page of each type (home, a category, a product, cart, first checkout step, search, sign-up and contact forms) without paying or submitting personal details, and prints the page types it found and the ones the site doesn't have.
13
+ - `aitd run --against <plan>` checks a run against a plan. `<plan>` is `latest`, `first`, a plan ID or a path to a plan file or folder; with `--against` alone the journeys are derived from the plan's trigger pages (at most six), and with `--journey` or `--goal` only the events expected on that flow are checked. The run records the plan ID in its report. The same option works on the `run_audit` and `finish_audit` MCP tools.
14
+ - The report has a "Plan vs. site" section for runs with `--against`, at the top of `report.html` and `report.md`, with a coverage score (`Coverage 7 of 11 (64%), 2 events not checked`). Each planned event is marked Implemented, Missing, Missing params, Wrong values, or Not checked, and unplanned events are listed. The same results are written to `plan-check.json`. Without a plan the report is unchanged.
15
+ - Each plan folder has a `plan.html` page showing its events, parameters, user properties and the consent-mode flag.
16
+ - `aitd plan list --site <url>` lists the plan IDs for a site. `aitd plan export <plan> --site <url>` writes a plan to `plan.xlsx` (or `events.csv` and `user_properties.csv` with `--format csv`), and `aitd plan import <file> --site <url>` saves an edited spreadsheet as a new plan. Import never changes an existing plan; errors name the tab, row and fix.
17
+ - Runs are saved in `aitd/<domain>/runs/<id>/` (report, timeline, capture and plan check) with IDs in local time. `--data-dir <dir>` moves the `aitd/` folder; it replaces `run --out`, which still works as a hidden alias for one minor version.
18
+ - The help is redesigned: a short `aitd --help` with the commands and three examples, and one help text per command that lists the essential options first. `--no-ai` now implies `--scripted`, and the missing-key error names the environment variables to set.
19
+ - `aitd plan --site` prints the page types it found, and `aitd run` without `--journey`, `--goal`, `--against` or journeys in the `--config` file stops before the browser or the model starts, so a run can't wander and spend API usage.
20
+ - Fixed: `npm test` no longer keeps running for about 15 minutes after the MCP tests. A refused `finish_audit` now says the audit is still open and to call it again.
21
+
22
+ **Breaking changes**
23
+
24
+ - The default output folder is now `./aitd`. Runs and plans are no longer written to `reports/`.
25
+ - `aitd plan --from` is removed. Draft a plan with `aitd plan --site <url>` instead.
26
+ - `plan --out` and `plan --force` are removed. Each plan is saved in a new folder, so nothing is replaced.
27
+ - `run --out` is replaced by `--data-dir <dir>`.
28
+ - `--providers` is renamed `--platforms`. The old name still works for one minor version and prints a note.
29
+
3
30
  ## 0.9.0 (2026-10-15)
4
31
 
5
32
  - `aitd run ... --save-steps <file>` writes the steps each journey took into `journeys[].steps` of that config file (creating it if needed, and adding the run's plan when the config has none). A later `aitd run --config <file> --scripted --no-ai` repeats them with no AI model or API key. A journey run on several viewports keeps the steps of its first viewport.
package/README.md CHANGED
@@ -25,7 +25,7 @@ Built by [Analitik İşler](https://analitikisler.com). MIT licensed.
25
25
  ✓ All scripted steps completed. · 20 tracking hits captured
26
26
 
27
27
  2 broken · 1 risk · 1 warning · 4 ok
28
- Report: reports/demo/report.html
28
+ Report: reports/demo/localhost/runs/2026-10-16_0800/report.html
29
29
  ```
30
30
 
31
31
  ## Why
@@ -48,14 +48,15 @@ Manual tag QA catches this, but it's tedious, so it rarely happens after every r
48
48
  | Consent | Meta `PageView` fired before the visitor accepted cookies, Consent Mode default missing or set too late, Consent Mode v2 signals (`ad_user_data`, `ad_personalization`) missing, tracking cookies set before consent, tags or cookies still active after the `decline_cookies` journey rejects the banner, a reject button that does nothing |
49
49
  | Personal data | An email address sent to an ad platform in plain text |
50
50
  | Unplanned events | Events firing that aren't in your measurement plan |
51
+ | Plan coverage | Each planned event sorted into implemented, missing, missing parameters, wrong values or not checked (see [Plan vs. site](#plan-vs-site)) |
51
52
 
52
53
  Platforms: GA4 (including server-side GTM endpoints and Google tag gateway paths on the site's own domain; hits to a server container are marked server-side, and Stape and Elevar requests are recognised), Google Ads conversions, Meta Pixel, TikTok Pixel, and basic X Pixel events.
53
54
 
54
- ### Choose the providers to check
55
+ ### Choose the platforms to check
55
56
 
56
- By default an audit checks GA4, Google Ads, Meta and TikTok. Pick others with `--providers ga4,meta,x`, `"providers"` in the config, or `providers` on the MCP `start_audit` and `run_audit` tools. You can choose from `ga4`, `google_ads`, `meta`, `tiktok`, `x`, `linkedin`, `microsoft_ads`, `pinterest`, `snapchat`, `clarity`, `hotjar`, `doubleclick` and `adsense`. Events are parsed for GA4, Google Ads, Meta, TikTok and X; the others show their network requests.
57
+ By default an audit checks GA4, Google Ads, Meta and TikTok. Pick others with `--platforms ga4,meta,x`, `"providers"` in the config, or `providers` on the MCP `start_audit` and `run_audit` tools. You can choose from `ga4`, `google_ads`, `meta`, `tiktok`, `x`, `linkedin`, `microsoft_ads`, `pinterest`, `snapchat`, `clarity`, `hotjar`, `doubleclick` and `adsense`. Events are parsed for GA4, Google Ads, Meta, TikTok and X; the others show their network requests. `--providers` still works as the old name of `--platforms` for one more minor version and prints a note.
57
58
 
58
- Requests to providers you didn't choose are still answered locally, so they never reach those accounts either. They are left out of the timeline, the CSV and the checks, and only counted: the report lists them with their request counts (for example "61 out-of-scope requests were skipped: Microsoft Clarity, DoubleClick"), and each step says how many it skipped. Without `--providers`, any provider your measurement plan names is added to the default list. Planned events for providers you did leave out are listed in one info finding instead of being reported as missing. Tag manager and consent platform requests are always shown.
59
+ Requests to platforms you didn't choose are still answered locally, so they never reach those accounts either. They are left out of the timeline, the CSV and the checks, and only counted: the report lists them with their request counts (for example "61 out-of-scope requests were skipped: Microsoft Clarity, DoubleClick"), and each step says how many it skipped. Without `--platforms`, any platform your measurement plan names is added to the default list. Planned events for platforms you did leave out are listed in one info finding instead of being reported as missing. Tag manager and consent platform requests are always shown.
59
60
 
60
61
  ## How it works
61
62
 
@@ -118,7 +119,7 @@ The global install also adds `aitd`, a short alias: `aitd run --site … --journ
118
119
 
119
120
  Or run it without installing: `npx -y @analitikisler/ai-tag-debugger run --site … --journey add_to_cart`.
120
121
 
121
- Run `ai-tag-debugger --help` to see every command and option, such as `--providers`, `--scripted` and `--no-ai`.
122
+ Run `aitd --help` to see the commands, and `aitd run --help` (or `plan`, `replay`, `mcp`) for each command's options.
122
123
 
123
124
  ### Try the demo shop (from source)
124
125
 
@@ -130,21 +131,142 @@ cd ai-tag-debugger
130
131
  npm install
131
132
  npx playwright install chromium # run again after upgrading, so the browser matches Playwright
132
133
  npm run demo:serve # in one terminal: http://localhost:4321
133
- node src/cli.js run --config examples/demo.config.json --out reports/demo
134
- open reports/demo/report.html
134
+ node src/cli.js run --config examples/demo.config.json --data-dir reports/demo
135
+ open reports/demo/localhost/runs/*/report.html
135
136
  ```
136
137
 
137
138
  No API key yet? Replay the fixed steps without any AI model:
138
139
 
139
140
  ```bash
140
- node src/cli.js run --config examples/demo.config.json --scripted --no-ai --out reports/demo
141
+ node src/cli.js run --config examples/demo.config.json --scripted --no-ai --data-dir reports/demo
141
142
  ```
142
143
 
144
+ ## Just ask
145
+
146
+ You don't have to learn the options first. Put a plain sentence in quotes and aitd turns it into the matching command, prints that command and asks `Run this? (Y/n)` before it runs anything:
147
+
148
+ ```bash
149
+ aitd "check my google analytics tags"
150
+ # aitd run --platforms ga4
151
+ # Run this? (Y/n)
152
+ ```
153
+
154
+ | You type | aitd runs |
155
+ |---|---|
156
+ | `"Check my google analytics tags"` | `aitd run --platforms ga4` |
157
+ | `"What changed on my site since the last run"` | `aitd run` (every run already reports what changed) |
158
+ | `"Compare my site against the plan"` | `aitd run --against latest` |
159
+ | `"What custom events does my site need"` | `aitd plan --topic custom-events` |
160
+ | `"Is my Meta pixel firing on checkout?"` | `aitd run --platforms meta --goal "reach checkout"` |
161
+ | `"Test signing up for the newsletter"` | `aitd run --goal "sign up for the newsletter"` |
162
+ | `"Does my purchase event send the right revenue?"` | `aitd run --journey purchase` |
163
+ | `"Make a tracking plan for example.com"` | `aitd plan --site https://example.com` |
164
+ | `"What ecommerce events should an online shop track?"` | `aitd plan --topic ecommerce` |
165
+ | `"Check TikTok and Google Ads on the contact form"` | `aitd run --platforms google_ads,tiktok --goal "submit the contact form"` |
166
+
167
+ Add `-y` to skip the question: `aitd -y "check my google analytics tags"`.
168
+
169
+ If a sentence leaves something out, aitd asks one short question instead of guessing: plan or run, which site, or what to test. Reports can't be filtered from a sentence yet (`"Show me only the errors from the last report"` says so). Without an AI key, a small keyword matcher handles the common phrases. With one, the AI reads any wording, but it can only pick options that exist, so it never invents a flag.
170
+
171
+ ## Plan, then audit
172
+
173
+ A run checks what a site sends against a **plan**: the events, parameters and user properties you expect. Three steps:
174
+
175
+ ```bash
176
+ # 1. Draft a plan. The AI explores the site and proposes what should be tracked.
177
+ aitd plan --site https://yoursite.com
178
+
179
+ # 2. Optional: edit it in a spreadsheet, then save the edited copy as a new plan.
180
+ aitd plan export latest --site https://yoursite.com # writes plan.xlsx next to the plan
181
+ aitd plan import plan.xlsx --site https://yoursite.com # saves a new plan; the old one is untouched
182
+
183
+ # 3. Audit the site against the plan.
184
+ aitd run --site https://yoursite.com --against latest
185
+ ```
186
+
187
+ **Drafting a plan** needs no tracking code. The AI explores one page of each type: the home page, a category, a product, the cart, the first checkout step, search, and any sign-up or contact forms. It never pays, and it never submits a form with personal details. `--provider`, `--model` and `--max-steps` (default 25, the most AI steps) work as they do for `run`. The output prints "Page types found" and "Not present on this site", so you can see which page types the AI reached. A small site, with only 2 pages, is fine.
188
+
189
+ To draft a plan for one kind of event only, add `--topic`: `custom-events`, `ecommerce`, `forms` or `consent`. The plan then covers just those events, and the rest of the plan format is unchanged:
190
+
191
+ ```bash
192
+ aitd plan --site https://yoursite.com --topic ecommerce
193
+ ```
194
+
195
+ The plan is saved in a new folder, `aitd/<domain>/plans/<id>/`, as `measurement-plan.json` and a readable `plan.html`. For each event it lists:
196
+
197
+ - `name` and `platform`. Events specific to your site, such as a size guide or a store locator, are marked `custom: true`.
198
+ - `description` and `trigger`: the page type and the visible label of the element that fires the event.
199
+ - `parameters`: each with a description and an example value. Custom parameters are marked. `required_params` lists the ones that must be present.
200
+ - `user_properties`: suggested ones such as `customer_type`, each with a description and an example.
201
+
202
+ Events your site already sends are marked `"seen": true`.
203
+
204
+ Review the plan before you use it. The examples and suggestions come from the pages the AI saw, so check that each event fits your business. The extra fields are ignored by the checks.
205
+
206
+ **Spreadsheet import and export.** `aitd plan export <plan> --site <url>` writes `plan.xlsx` next to the plan, with one row per event parameter on an `events` tab (`event, platform, parameter, required, example, trigger, description`) and one row per user property on a `user_properties` tab. Add `--format csv` to get `events.csv` and `user_properties.csv` instead; CSV needs no extra package. `.xlsx` uses one small library, `fflate`, which is installed with the tool as an optional dependency. `aitd plan import <file> --site <url>` reads the spreadsheet back and saves it as a new plan folder. Import never edits an existing plan. Unknown columns are ignored with a warning, and an error names the tab, row and fix, for example `events, row 7: "required" must be yes or no (found "maybe").`
207
+
208
+ `measurement-plan.json` looks like this:
209
+
210
+ ```json
211
+ {
212
+ "consent_mode": true,
213
+ "events": [
214
+ { "platform": "ga4", "name": "add_to_cart", "required_params": ["currency", "value", "items"] },
215
+ { "platform": "ga4", "name": "purchase", "journeys": ["checkout"], "required_params": ["transaction_id", "currency", "value", "items"] },
216
+ { "platform": "meta", "name": "Purchase", "journeys": ["checkout"], "required_params": ["value", "currency"] }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ `platform` is `ga4`, `google_ads`, `meta` or `tiktok`. `journeys` limits where an event is expected (default: every journey). Set `allow_multiple: true` for events that may legitimately fire more than once per action.
222
+
223
+ Event names are matched loosely, so `dl_add_to_cart` (Elevar), `addToCart` and `Add To Cart` count as `add_to_cart`, and `transaction` or `order_completed` as `purchase`. Add your own with `"aliases": ["my_event"]` on a planned event. Required parameters are also found under their usual other names: `products` for `items`, `revenue` for `value`, `order_id` for `transaction_id`.
224
+
225
+ **Auditing against a plan.** `run --against <plan>` takes `latest` (or `last`), `first`, a plan ID, or a path to a plan file or its folder. When `--site` is not given, the site comes from the plan. Give the run a journey as well and it walks only that flow, checking only the plan events expected there; the rest of the plan is reported as not checked, never as missing. Used alone, `--against` derives up to six journeys from the plan: it groups the planned events by the page they are triggered on and makes one journey per page, at most six (the smallest groups share the last journey), with no extra AI call. The chosen journeys are printed before the browser starts. Every report header then says `Checked against plan <id>`.
226
+
227
+ `run` needs something to test: `--against`, `--journey`, `--goal`, or journeys in your config file. Without one, it stops before opening the browser with `Nothing to test. Add --against latest, --journey <id> or --goal "<text>".`, so it can't wander and spend API usage. If a site has no plan yet, `run --against` says `No plan yet for example.com. Draft one with: aitd plan --site https://example.com`.
228
+
229
+ `aitd plan list --site <url>` lists the site's plan IDs, oldest first.
230
+
231
+ ### Plan vs. site
232
+
233
+ When a run uses `--against`, the report starts with a **Plan vs. site** section, in `report.html` and `report.md`. Each planned event lands in one bucket:
234
+
235
+ | Bucket | Meaning |
236
+ |---|---|
237
+ | Implemented | Planned, fired, all required parameters present, no value problems |
238
+ | Missing | Planned for a journey the run walked, but never fired |
239
+ | Missing params | Fired, but a required parameter is absent |
240
+ | Wrong values | Fired with a value problem, from the same checks as purchase value, currency and items |
241
+ | Unplanned | Fired, but isn't in the plan |
242
+ | Not checked | Planned, but its journey or platform wasn't part of this run |
243
+
244
+ The coverage score is implemented divided by the planned events that were checkable (all except not checked), shown overall and per platform, for example `Coverage 7 of 11 (64%), 2 events not checked`. The same entries are in `plan-check.json`, one per planned event with its bucket. Exit codes don't change: `--fail-on` still looks at finding severity. Without `--against`, the report is exactly as before.
245
+
246
+ ### Folder layout and plan IDs
247
+
248
+ Plans and runs are kept in `aitd/` in the folder you run the tool from:
249
+
250
+ ```
251
+ aitd/
252
+ example.com/ the site's host, without www.
253
+ plans/2026-10-16_0900/ measurement-plan.json, plan.html, plan.xlsx (after an export)
254
+ runs/2026-10-16_0912/ report.html, report.md, timeline.csv, capture.json
255
+ and plan-check.json (with --against)
256
+ ```
257
+
258
+ An ID is the local time, `YYYY-MM-DD_HHMM`. When that minute is already taken, seconds are added (`_HHMMSS`). Nothing is ever replaced: each draft, import and run gets a new folder. Use `--data-dir <dir>` to keep the `aitd/` folder somewhere else. `replay` and `--save-site` folders are not affected.
259
+
260
+ Each report opens with a "Changed since last run" section that compares the run with the site's previous one in `runs/`, for example `2 events fixed, 1 new problem`, and lists each one. When both runs used `--against`, it compares plan coverage (an event that went from Missing to Implemented is fixed); otherwise it compares the health findings. The first run for a site says there is nothing to compare yet. There is no flag to set. The comparison is also saved under `changes` in `capture.json`.
261
+
143
262
  ## Choose what to test
144
263
 
145
- You don't need a config file to start. Pick ready-made journeys, describe your own in plain language, and narrow the check to the events you care about:
264
+ You don't need a config file to start. Pick ready-made journeys, describe your own in plain language, check against a plan, and narrow the check to the events you care about:
146
265
 
147
266
  ```bash
267
+ # Check the site against its latest saved plan.
268
+ aitd run --site https://staging.yourshop.com --against latest
269
+
148
270
  # Ready-made journeys come with a goal and the GA4 and Meta events to expect.
149
271
  ai-tag-debugger run --site https://staging.yourshop.com --journey purchase --journey sign_up
150
272
 
@@ -165,6 +287,8 @@ ai-tag-debugger run --config ai-tag-debugger.config.json --events purchase,add_t
165
287
 
166
288
  `--journey` also picks journeys from your config by id. With a config, ready-made journeys add their events to your plan.
167
289
 
290
+ Not sure what to test? `aitd plan --site https://yoursite.com` drafts a measurement plan, and `--against latest` checks the site against it.
291
+
168
292
  ### Keeping API usage down
169
293
 
170
294
  Each browsing step is one model call, so usage grows with **journeys × viewports × steps**, plus one call at the end to explain the findings. The checks themselves never call the model.
@@ -223,15 +347,15 @@ When a journey ran on both viewports, only the first viewport's steps are kept.
223
347
  | Field | Meaning |
224
348
  |---|---|
225
349
  | `site` | Base URL. Use staging when you can. |
226
- | `plan` | Measurement plan: a file path or an inline object (below). Optional with ready-made journeys. |
350
+ | `plan` | Measurement plan: a file path or an inline object (below). Optional with ready-made journeys. A run with `--against` uses that plan instead. |
227
351
  | `gtm_container` | Optional GTM container export (Admin → Export container), so explanations can name tags and triggers. |
228
352
  | `viewports` | `desktop` and/or `mobile`. |
229
- | `journeys` | Optional when you pick ready-made journeys with `--journey` or describe one with `--goal`. |
353
+ | `journeys` | Optional when you pick ready-made journeys with `--journey`, describe one with `--goal`, or check against a plan with `--against`. |
230
354
  | `journeys[].goal` | What the AI should do, in plain language. |
231
355
  | `journeys[].start` | Optional start path (default `/`). |
232
356
  | `journeys[].steps` | Optional fixed steps for `--scripted` runs: `{ "action": "click", "selector": "#add-to-cart" }`. |
233
357
  | `allowed_hosts` | Other hosts journeys may visit, e.g. `["checkout.payments-provider.com"]` for a hosted checkout. The browser otherwise stays on the `site` host and its subdomains. Same as `--allow-host`. |
234
- | `providers` | Tracking providers to check, e.g. `["ga4", "meta"]`. Default `["ga4", "google_ads", "meta", "tiktok"]`. Same as `--providers`. |
358
+ | `providers` | Tracking platforms to check, e.g. `["ga4", "meta"]`. Default `["ga4", "google_ads", "meta", "tiktok"]`. Same as `--platforms`. |
235
359
  | `block_hits` | Default `true`. Set to `false` to let hits reach your real endpoints. |
236
360
  | `language` | Report language, `en` (default) or `tr`. Same as `--lang`. |
237
361
  | `keep_bodies` | Default `false`. Set to `true` to store tracking requests as sent, without redacting user data. Same as `--keep-bodies`. |
@@ -239,55 +363,77 @@ When a journey ran on both viewports, only the first viewport's steps are kept.
239
363
  | `provider` | Optional: `anthropic`, `openai`, `gemini` or `openai-compatible`. Same as `--provider`. |
240
364
  | `base_url`, `model` | Optional: the API address and model id, e.g. for `openai-compatible`. Same as `--base-url` and `--model`. |
241
365
 
242
- `measurement-plan.json`:
243
-
244
- ```json
245
- {
246
- "consent_mode": true,
247
- "events": [
248
- { "platform": "ga4", "name": "add_to_cart", "required_params": ["currency", "value", "items"] },
249
- { "platform": "ga4", "name": "purchase", "journeys": ["checkout"], "required_params": ["transaction_id", "currency", "value", "items"] },
250
- { "platform": "meta", "name": "Purchase", "journeys": ["checkout"], "required_params": ["value", "currency"] }
251
- ]
252
- }
253
- ```
254
-
255
- `platform` is `ga4`, `google_ads`, `meta` or `tiktok`. `journeys` limits where an event is expected (default: every journey). Set `allow_multiple: true` for events that may legitimately fire more than once per action.
256
-
257
- Event names are matched loosely, so `dl_add_to_cart` (Elevar), `addToCart` and `Add To Cart` count as `add_to_cart`, and `transaction` or `order_completed` as `purchase`. Add your own with `"aliases": ["my_event"]` on a planned event. Required parameters are also found under their usual other names: `products` for `items`, `revenue` for `value`, `order_id` for `transaction_id`.
258
-
259
366
  ## CLI
260
367
 
261
368
  ```
262
- ai-tag-debugger run [--site <url>] [--config <file>] [--journey <id>] [--goal "<text>"] [--events <names>]
263
- [--max-steps <n>] [--out <dir>] [--viewport desktop|mobile] [--providers <list>]
264
- [--provider anthropic|openai|gemini|openai-compatible] [--model <id>] [--base-url <url>]
265
- [--lang en|tr] [--allow-host <host>] [--keep-bodies] [--scripted] [--no-ai] [--fail-on broken|risk|warning|never] [--headed]
266
- [--save-site <dir>] [--save-steps <file>]
267
- ai-tag-debugger replay <dir>... [--update] [--out <dir>]
268
- ai-tag-debugger mcp [--http] [--port <n>] [--host <addr>] [--token <secret>] [--public-url <https url>] [--reports <dir>]
269
- [--allow-private-network]
369
+ aitd "<sentence>" [-y]
370
+ aitd plan --site <url> [--topic <name>] [--headed] [--provider <name>] [--model <id>] [--max-steps <n>] [--data-dir <dir>]
371
+ aitd plan list --site <url> [--data-dir <dir>]
372
+ aitd plan import <file> --site <url> [--data-dir <dir>]
373
+ aitd plan export <plan> --site <url> [--format xlsx|csv] [--data-dir <dir>]
374
+ aitd run --site <url> (--against <plan> | --journey <id> | --goal "<text>") [--config <file>] [--events <names>]
375
+ [--max-steps <n>] [--viewport desktop|mobile] [--platforms <list>] [--data-dir <dir>]
376
+ [--provider anthropic|openai|gemini|openai-compatible] [--model <id>] [--lang en|tr] [--headed]
377
+ [--fail-on broken|risk|warning|never] [--scripted] [--no-ai] [--save-site <dir>] [--save-steps <file>]
378
+ aitd replay <dir>... [--update] [--out <dir>]
379
+ aitd mcp [--http] [--port <n>] [--host <addr>] [--token <secret>] [--public-url <https url>] [--reports <dir>]
380
+ [--allow-private-network]
270
381
  ```
271
382
 
272
- `aitd` is a short alias for `ai-tag-debugger` and takes the same commands and options.
383
+ `aitd` is a short alias for `ai-tag-debugger` and takes the same commands and options. Run `aitd <command> --help` for the essential options of each command.
384
+
385
+ ### All options
386
+
387
+ | Option | Commands | Meaning |
388
+ |---|---|---|
389
+ | `--site <url>` | plan, run | The site. Required for `plan`; for `run`, needed unless `--against` or the config gives it. |
390
+ | `--against <plan>` | run | Check against a plan: `latest` (or `last`), `first`, a plan ID, or a path to a plan file or folder. |
391
+ | `--journey <id>` | run | A ready-made journey (repeatable). |
392
+ | `--goal "<text>"` | run | A journey in plain language (repeatable). |
393
+ | `--config <file>` | run | Take the site, journeys and plan from a config file. |
394
+ | `--events <names>` | run | Only check these events, e.g. `purchase,add_to_cart`. |
395
+ | `--viewport <name>` | run | `desktop` or `mobile` (repeatable). |
396
+ | `--platforms <list>` | run | Platforms to check, e.g. `ga4,meta`. Replaces `--providers`, which still works for one more minor version. |
397
+ | `--max-steps <n>` | plan, run | The most AI steps per journey (default 25 for `plan`). |
398
+ | `--lang <code>` | run | Report language: `en` or `tr`. |
399
+ | `--fail-on <level>` | run | Exit with 1 at this level: `broken` (default), `risk`, `warning` or `never`. |
400
+ | `--headed` | plan, run | Show the browser window. |
401
+ | `--provider <name>`, `--model <id>` | plan, run | The AI provider and model. Default: whichever API key is set. |
402
+ | `--scripted` | run | Replay each journey's fixed steps, with no AI navigation. |
403
+ | `--no-ai` | run | No AI model at all. Implies `--scripted`. |
404
+ | `--save-site <dir>` | run | Save the site's responses for `replay`. |
405
+ | `--save-steps <file>` | run | Write the steps each journey took into a config file. |
406
+ | `--data-dir <dir>` | plan, run | Where `aitd/` (plans and runs) is kept. Default: `./aitd`. Replaces `run --out`. |
407
+ | `--format xlsx\|csv` | plan export | The spreadsheet format. Default: `xlsx`. |
408
+ | `--update` | replay | Make this replay's findings the expected ones. |
409
+ | `--out <dir>` | replay | Where to write the replay reports. For `run`, `--out` still works as a hidden alias for one minor version and prints a note; use `--data-dir`. |
410
+ | `--base-url <url>` | run | The API address for an OpenAI-compatible provider. |
411
+ | `--allow-host <host>` | run | Another host journeys may visit (repeatable). Same as `allowed_hosts`. |
412
+ | `--keep-bodies` | run | Store tracking requests as sent, without redacting user data. |
413
+ | `--no-branding` | plan, run | Leave the logo and credit line out of the reports and `plan.html`. |
414
+ | `--http`, `--port`, `--host`, `--token`, `--public-url`, `--reports`, `--allow-private-network` | mcp | See the MCP section below. |
415
+
416
+ Removed in 0.10.0: `plan --from`, `plan --out` and `plan --force`. Drafting a plan always saves a new folder, and a removed flag prints what to run instead.
273
417
 
274
418
  The exit code is `1` when findings reach `--fail-on` (default `broken`), so it can gate a deploy. See [`examples/github-actions/ai-tag-debugger.yml`](examples/github-actions/ai-tag-debugger.yml) for running it after every deployment.
275
419
 
276
420
  Output:
277
421
 
278
422
  - `report.html`: one file with four tabs. Links work across tabs (a finding's "Where" chip opens that step), and every view has its own URL you can bookmark or share.
279
- - **Overview**: problem counts, the AI summary (most important problem first, plus things worth checking that the findings don't cover), the journeys with their problem counts, and the providers checked.
423
+ - **Overview**: problem counts, the AI summary (most important problem first, plus things worth checking that the findings don't cover), the journeys with their problem counts, the providers checked, and, with `--against`, the [Plan vs. site](#plan-vs-site) coverage.
280
424
  - **Findings**: grouped by severity and filterable. Each one has its impact, likely cause, evidence, numbered fix steps and the steps where it happened.
281
425
  - **Journeys**: one journey at a time, with its steps on the left and the selected step on the right. It opens on the first step with a problem. Each step has three tabs:
282
426
  - **Events**: each tracking hit with its parameters, consent state, the dataLayer push and request behind it, and a note when a finding points at it.
283
427
  - **dataLayer**: every push in the step.
284
- - **Network requests**: every request to the chosen providers, decoded into a parameter table with a `?` tip on each parameter. A batched GA4 request shows each of its events.
285
- - **Scope and plan**: whether each planned event was sent on each journey, and the providers checked or left out, with request counts.
428
+ - **Network requests**: every request to the chosen platforms, decoded into a parameter table with a `?` tip on each parameter. A batched GA4 request shows each of its events.
429
+ - **Scope and plan**: whether each planned event was sent on each journey, and the platforms checked or left out, with request counts.
286
430
 
287
431
  Events and requests can be filtered by source. GA4 item strings (`pr1`…) and dataLayer `ecommerce.items` are shown as item cards, with custom item parameters in their own group. The report has no scripts: tabs and filters are plain HTML and CSS (they need Chrome 105, Safari 15.4 or Firefox 121 or newer), and printing shows every tab. The logos are embedded, so nothing is loaded from the internet. `--no-branding` leaves out the Analitik İşler logo and credit line.
288
432
  - `timeline.csv`: the same timeline as one row per hit, dataLayer push and network call, ready for Excel or Google Sheets.
289
433
  - `report.md`: the report in Markdown, e.g. for a pull request comment.
290
434
  - `capture.json`: everything captured, for your own analysis.
435
+ - `plan-check.json`: with `--against`, one entry per planned event with its bucket.
436
+ - `plan.html` (in the plan's folder): a readable page of the plan's events, parameters and user properties.
291
437
 
292
438
  Reports end with a credit line, "Generated by AI Tag Debugger · analitikisler.com", where the domain is a plain link (no images, no tracking, and no referrer, so report URLs aren't leaked). `--no-branding` removes it along with the logo.
293
439
 
@@ -295,17 +441,20 @@ Use `--lang tr` for a Turkish report. Finding texts, headings, and the model's e
295
441
 
296
442
  ## Use it from your AI chat app (MCP)
297
443
 
298
- `ai-tag-debugger mcp` starts a [Model Context Protocol](https://modelcontextprotocol.io) server. Your chat app's model then runs the audit itself: you ask "check the tracking on the checkout of staging.myshop.com" and it opens the browser, clicks through, and explains the findings in the chat. No API key is needed, because the app's own model does the thinking.
444
+ `aitd mcp` starts a [Model Context Protocol](https://modelcontextprotocol.io) server. Your chat app's model then runs the audit itself: you ask "check the tracking on the checkout of staging.myshop.com" and it opens the browser, clicks through, and explains the findings in the chat. No API key is needed, because the app's own model does the thinking.
299
445
 
300
446
  Tools the server offers:
301
447
 
302
448
  | Tool | What it does |
303
449
  |---|---|
304
- | `start_audit` | Opens a fresh browser on a URL and starts recording all tracking. Pass a ready-made journey (`purchase`, `sign_up`, …) to get its goal and expected events, and `providers` to choose what to check. The assistant asks you which platforms to check first. |
450
+ | `make_plan` | Drafts a tracking plan for a site (what should be tracked), the same as `aitd plan --site`. Pass `topic` (`custom-events`, `ecommerce`, `forms`, `consent`) to limit it to one kind of event. The plan is saved and its ID can be given as `against` to `finish_audit`. It uses the AI provider configured on the computer that runs the server and takes a few minutes. |
451
+ | `start_audit` | Opens a fresh browser on a URL and starts recording all tracking. Pass a ready-made journey (`purchase`, `sign_up`, …) to get its goal and expected events, and `providers` to choose the platforms to check. The assistant asks you which platforms to check first. |
305
452
  | `browser_action` | One click, fill, select, goto, scroll or wait. Returns the page and the tracking hits that step sent. |
306
453
  | `get_page` | Shows the current page. |
307
- | `finish_audit` | Checks everything against your measurement plan (JSON) or the ready-made journey's events, optionally only the `events` you name, and writes the full HTML report with the timeline. |
308
- | `run_audit` | Runs a config file end to end (local only). |
454
+ | `finish_audit` | Checks everything against your measurement plan (JSON), a saved one given as `against` (`latest`, `first`, a plan ID, or on a local server a path), or the ready-made journey's events, optionally only the `events` you name, and writes the full HTML report with the timeline. The site comes from the audit. |
455
+ | `run_audit` | Runs a config file end to end. With `against`, it checks the run against a saved plan and, when the config has no journeys, walks the journeys derived from that plan. Local only for file paths. |
456
+
457
+ `against` takes the same values as the CLI's `--against`. Over HTTP it takes only `latest`, `first` or a plan ID, never a path. Plans are the ones saved by `aitd plan --site <url>` or by `make_plan`. Ask for a plan when you want to know what to track, and for an audit when you want to know what the site sends.
309
458
 
310
459
  The browser runs on the computer where the server runs, so it can reach your staging and `localhost` sites. Tracking requests are answered locally as usual.
311
460
 
@@ -350,7 +499,7 @@ The server prints a URL with a random secret path, like `https://<your-tunnel-ad
350
499
 
351
500
  In HTTP mode, the server is more locked down than locally:
352
501
 
353
- - It doesn't read measurement plans or configs from your disk (pass the plan as JSON text in the chat), and `run_audit` isn't offered. It only serves the reports it wrote itself.
502
+ - It doesn't read measurement plans or configs from your disk (pass the plan as JSON text in the chat, or name a saved plan with `against: latest`, `first` or its ID), and `run_audit` isn't offered. It only serves the reports it wrote itself.
354
503
  - The browser opens only `http` and `https` pages, and refuses `localhost` and private network addresses (such as `192.168.x.x` or `169.254.169.254`), so the URL can't be used to look into your network. All browser traffic, WebSockets included, goes through a small built-in proxy that resolves each host once and connects only to the address it checked, so a DNS answer that changes mid-audit can't get around the check. To audit a local staging site this way anyway, start the server with `--allow-private-network`.
355
504
  - Audits left open for 15 minutes are closed, and request bodies are limited to 1 MB.
356
505