@ainyc/canonry 1.46.0 → 1.48.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.
@@ -0,0 +1,130 @@
1
+ # AEO Analysis: Interpreting Canonry Results
2
+
3
+ ## What Citation Means
4
+
5
+ A "cited" keyword means the client's domain appeared in an AI provider's response when that query was asked. It does NOT mean:
6
+ - The AI recommended them positively
7
+ - The citation is prominent
8
+ - It will persist on the next sweep
9
+
10
+ A "not-cited" keyword means the AI answered without mentioning the client at all.
11
+
12
+ ## Reading Evidence Output
13
+
14
+ ```
15
+ ✓ cited AEO Agency NYC ← branded/direct match
16
+ ✓ cited best plumber brooklyn
17
+ ✗ not-cited how to fix a leaky faucet ← informational gap: no page for this topic
18
+ ✗ not-cited emergency plumber near me ← competitive gap: others cited instead
19
+ ```
20
+
21
+ ### Keyword Categories
22
+
23
+ **Branded/direct keywords** (e.g., "[business name] [city]"):
24
+ - If cited: good — entity is established for core queries
25
+ - If not cited: urgent — something broken at a fundamental level (indexing, schema, llms.txt)
26
+
27
+ **Competitive keywords** (e.g., "best [service] [city]"):
28
+ - If not cited: check who IS cited — competitor analysis needed
29
+ - Harder wins; require established authority and trust signals
30
+
31
+ **Informational/how-to keywords** (e.g., "how to [do X]"):
32
+ - If not cited: almost always a content gap — no page targeting this topic, or it's not indexed
33
+ - High-leverage — informational content positions a site as authoritative to AI models
34
+
35
+ ## Using Analytics
36
+
37
+ ### Citation Rate Trends (`--feature metrics`)
38
+ Shows citation rate over time across providers. Use to identify:
39
+ - Improving or declining visibility trends
40
+ - Provider-specific performance differences
41
+ - Impact of content/indexing changes over time
42
+
43
+ **Key phrase normalization:** When new key phrases are added to a project mid-history, canonry automatically normalizes each time bucket to only include key phrases that existed before that bucket started. This prevents newly-added (typically uncited) key phrases from creating a false drop in the citation rate trend. The chart displays dashed vertical annotation lines at points where key phrases were added (e.g. "+3 kp"), and each bucket's tooltip shows the key phrase count ("kp") used for that bucket's calculation.
44
+
45
+ ### Gap Analysis (`--feature gaps`)
46
+ Categorizes keywords as cited, gap (competitor cited but you're not), or uncited (nobody cited). Priorities:
47
+ - **Gap keywords** are highest priority — competitors are winning these
48
+ - **Uncited keywords** may need content or may be too broad
49
+
50
+ ### Source Breakdown (`--feature sources`)
51
+ Shows which source categories AI models cite for your keywords. Helps identify:
52
+ - Whether competitors dominate specific categories
53
+ - Content format opportunities (FAQ, how-to, comparison pages)
54
+
55
+ ## Diagnosing Citation Gaps
56
+
57
+ ### Step 1: Check indexing first
58
+ Not cited ≠ bad content. Often the page isn't indexed yet.
59
+ ```bash
60
+ canonry google coverage <project>
61
+ ```
62
+ If key pages are "unknown to Google," submit them before drawing conclusions.
63
+
64
+ ### Step 2: Check if content exists
65
+ Is there a page on the site targeting that keyword? If not, that's the gap — not a canonry or provider issue.
66
+
67
+ ### Step 3: Check competitors
68
+ For competitive keywords, if others are cited and the client isn't:
69
+ - Do competitors have more specific, dedicated pages?
70
+ - Do they have stronger schema/structured data?
71
+ - Are they more established in the index?
72
+
73
+ Run `canonry evidence <project> --format json` and check `competitorOverlap` in snapshots.
74
+
75
+ ### Step 4: Check across providers
76
+ Gemini, OpenAI, Claude, and Perplexity may behave differently. One citing a domain while another doesn't is normal — each has its own knowledge base and update schedule.
77
+
78
+ ### Step 5: Check analytics trends
79
+ ```bash
80
+ canonry analytics <project> --feature gaps --window 30d
81
+ ```
82
+ Look for patterns: are gaps growing or shrinking? Are new competitors appearing?
83
+
84
+ ## Trend Interpretation
85
+
86
+ **Stable cited** — monitor for regressions, no action needed.
87
+
88
+ **New citation** (was not-cited, now cited) — win. Correlate with what changed: new content, indexing, schema update.
89
+
90
+ **Regression** (was cited, now not-cited) — investigate immediately:
91
+ - Did a competitor page launch?
92
+ - Did the page get deindexed or go down?
93
+ - Did the model update?
94
+ - Check `canonry google deindexed <project>` for index losses
95
+
96
+ **Fluctuation** (cited in some runs, not others) — normal for competitive keywords. Track trend over 5+ runs before drawing conclusions. AI answers are non-deterministic.
97
+
98
+ ## What to Recommend
99
+
100
+ ### Low overall citation (< 50%)
101
+ 1. Audit indexing — `canonry google coverage <project>`
102
+ 2. Submit unindexed pages to Google Indexing API
103
+ 3. Submit sitemap to Bing WMT + send IndexNow batch
104
+ 4. Check core pages for schema (LocalBusiness / Organization / FAQPage)
105
+ 5. Map uncited keywords to pages — which have no corresponding page?
106
+
107
+ ### Branded terms not cited
108
+ Red flag. Check:
109
+ - Is the homepage indexed?
110
+ - Does `llms.txt` exist and list the business clearly?
111
+ - Does schema include the exact brand name in `name` field?
112
+
113
+ ### Informational terms not cited
114
+ Content strategy play:
115
+ - Does a page targeting this topic exist? If not, create it.
116
+ - Is it indexed? If not, submit it.
117
+ - Is it structured for AI extraction? (FAQ schema, clear H2s, definition-style answers)
118
+
119
+ ### Provider variance (cited on one, not others)
120
+ Expected — each provider has independent knowledge. Focus on the ones that matter most for the client's audience. Don't over-optimize for one provider at the expense of others.
121
+
122
+ ## The AEO Timeline Reality
123
+
124
+ - Site changes → weeks/months to appear in sweeps (or never)
125
+ - Google indexing → 24–72h with Indexing API, longer organic
126
+ - Bing indexing → hours with IndexNow, days without
127
+ - Model training updates → unknown schedule, outside our control
128
+
129
+ **Never say:** "Deploy this and re-run canonry to see if it worked."
130
+ **Always say:** "This positions the site correctly. Canonry will tell us if/when that pays off."
@@ -0,0 +1,349 @@
1
+ # Canonry CLI Reference
2
+
3
+ ## Server Management
4
+
5
+ ```bash
6
+ canonry init # interactive setup
7
+ canonry bootstrap # non-interactive setup from env vars
8
+ canonry start # start daemon
9
+ canonry stop # stop daemon
10
+ canonry serve # foreground mode
11
+ canonry serve --host 0.0.0.0 --port 4100
12
+ canonry --version
13
+ ```
14
+
15
+ Production managed by PM2:
16
+ ```bash
17
+ pm2 status
18
+ pm2 logs canonry
19
+ pm2 restart canonry
20
+ ```
21
+
22
+ ## Project Management
23
+
24
+ ```bash
25
+ canonry project list # list all projects
26
+ canonry project create <name> --domain <url> --country US --language en
27
+ canonry project show <name> # project detail
28
+ canonry project update <name> # update project settings
29
+ canonry project delete <name> # delete a project
30
+ canonry status <project> # citation summary + domain info
31
+ ```
32
+
33
+ ### Locations
34
+
35
+ Projects support multi-region location context for geographically-aware sweeps:
36
+
37
+ ```bash
38
+ canonry project add-location <name> --label "NYC" --city "New York" --region NY --country US
39
+ canonry project locations <name> # list configured locations
40
+ canonry project set-default-location <name> <label>
41
+ canonry project remove-location <name> <label>
42
+ ```
43
+
44
+ ## Sweeps
45
+
46
+ ```bash
47
+ canonry snapshot "Acme Corp" --domain acme.example.com # one-shot sales snapshot
48
+ canonry snapshot "Acme Corp" --domain acme.example.com --md # save markdown report
49
+ canonry snapshot "Acme Corp" --domain acme.example.com --output report.md # custom path
50
+ canonry snapshot "Acme Corp" --domain acme.example.com --pdf # save PDF report
51
+ canonry snapshot "Acme Corp" --domain acme.example.com --format json
52
+
53
+ canonry run <project> # sweep all configured providers
54
+ canonry run <project> --provider gemini # single provider only
55
+ canonry run <project> --wait # block until complete
56
+ canonry run <project> --location <label> # run with specific location context
57
+ canonry run <project> --all-locations # run for every configured location
58
+ canonry run <project> --no-location # explicitly skip location context
59
+ canonry run --all --wait # all projects
60
+ canonry run cancel <project> [run-id] # force-cancel stuck runs
61
+ canonry runs <project> --limit 10 # list recent runs
62
+ canonry run show <id> # show run details
63
+ ```
64
+
65
+ Run statuses: `queued` → `running` → `completed` / `failed` / `partial`
66
+
67
+ `partial` = some providers failed (usually rate limits) — successful snapshots are still saved.
68
+
69
+ `snapshot` does not create a project or write to the DB. It generates category queries, runs providers, and produces a report for prospecting.
70
+
71
+ ## Citation Data
72
+
73
+ ```bash
74
+ canonry evidence <project> # per-keyword cited/not-cited
75
+ canonry evidence <project> --format json # JSON output
76
+ canonry history <project> # audit trail
77
+ canonry export <project> --include-results # export as YAML
78
+ canonry backfill answer-visibility # recompute answer visibility from stored answers
79
+ canonry backfill answer-visibility --project <name> --format json
80
+ ```
81
+
82
+ Output shows:
83
+ - `✓ cited` — domain appeared in AI response for that keyword
84
+ - `✗ not-cited` — domain did not appear
85
+ - Summary: `Cited: X / Y`
86
+
87
+ ## Analytics
88
+
89
+ ```bash
90
+ canonry analytics <project> # default analytics view
91
+ canonry analytics <project> --feature metrics # citation rate trends
92
+ canonry analytics <project> --feature gaps # brand gap analysis (cited/gap/uncited)
93
+ canonry analytics <project> --feature sources # source breakdown by category
94
+ canonry analytics <project> --window 7d # time window: 7d, 30d, 90d, all
95
+ ```
96
+
97
+ ## Intelligence
98
+
99
+ ```bash
100
+ canonry insights <project> # list active insights (regressions, gains, opportunities)
101
+ canonry insights <project> --dismissed # include dismissed insights
102
+ canonry insights <project> --format json # JSON output
103
+ canonry insights dismiss <project> <id> # dismiss an insight
104
+ canonry health <project> # latest citation health snapshot
105
+ canonry health <project> --history # health trend over time
106
+ canonry health <project> --history --limit 10 # limit history entries
107
+ canonry health <project> --format json # JSON output
108
+ canonry backfill insights <project> # backfill insights for all completed runs
109
+ canonry backfill insights <project> --from-run <id> --to-run <id> # backfill a range
110
+ ```
111
+
112
+ ## Keywords & Competitors
113
+
114
+ ```bash
115
+ canonry keyword add <project> "phrase one" "phrase two"
116
+ canonry keyword remove <project> "phrase"
117
+ canonry keyword list <project>
118
+ canonry keyword import <project> keywords.txt
119
+ canonry keyword generate <project> --provider gemini --count 10 --save
120
+
121
+ canonry competitor add <project> competitor1.com competitor2.com
122
+ canonry competitor list <project>
123
+ ```
124
+
125
+ ## Scheduling & Notifications
126
+
127
+ ```bash
128
+ canonry schedule set <project> --preset daily # or: weekly, twice-daily, daily@09
129
+ canonry schedule set <project> --cron "0 9 * * *" --timezone America/New_York
130
+ canonry schedule show <project>
131
+ canonry schedule enable <project>
132
+ canonry schedule disable <project>
133
+ canonry schedule remove <project>
134
+
135
+ canonry notify add <project> --webhook <url> --events citation.lost,citation.gained
136
+ canonry notify events # list all available event types
137
+ canonry notify list <project>
138
+ canonry notify remove <project> <id>
139
+ canonry notify test <project> <id>
140
+ ```
141
+
142
+ Available events: `citation.lost`, `citation.gained`, `run.completed`, `run.failed`, `insight.critical`, `insight.high`
143
+
144
+ `insight.critical` and `insight.high` fire when the intelligence engine generates critical- or high-severity insights after a sweep completes.
145
+
146
+ ## Provider Settings & Quotas
147
+
148
+ ```bash
149
+ canonry settings # show config: providers, apiUrl, db path
150
+ canonry settings --format json
151
+ canonry settings provider gemini --api-key <KEY> --model gemini-2.5-flash
152
+ canonry settings provider openai --max-per-day 1000 --max-per-minute 20
153
+ canonry settings provider perplexity --api-key <KEY>
154
+ ```
155
+
156
+ Quota flags: `--max-concurrent`, `--max-per-minute`, `--max-per-day`
157
+
158
+ Available providers: `gemini`, `openai`, `claude`, `perplexity`, `local`, `cdp`
159
+
160
+ If a provider hits rate limits (429 errors), the run completes as `partial`. Reduce concurrency or increase time between sweeps.
161
+
162
+ ### Gemini Vertex AI
163
+
164
+ Gemini supports Vertex AI as an alternative to API key authentication. Use GCP Application Default Credentials (ADC) or a service account JSON key file:
165
+
166
+ ```bash
167
+ # Via env vars (recommended for servers)
168
+ export GEMINI_VERTEX_PROJECT=my-gcp-project
169
+ export GEMINI_VERTEX_REGION=us-central1 # optional, defaults to us-central1
170
+ export GEMINI_VERTEX_CREDENTIALS=/path/to/sa.json # optional, falls back to ADC
171
+
172
+ # Or in canonry.yaml config
173
+ # vertexProject, vertexRegion, vertexCredentials fields under provider config
174
+ ```
175
+
176
+ When Vertex AI is configured, no `GEMINI_API_KEY` is required. The provider uses the `@google-cloud/vertexai` SDK with `googleAuthOptions` for credential handling.
177
+
178
+ ## Google Search Console
179
+
180
+ ```bash
181
+ canonry google connect <project> # initiate OAuth flow
182
+ canonry google disconnect <project> # disconnect GSC
183
+ canonry google status <project> # connection status
184
+ canonry google properties <project> # list available properties
185
+ canonry google set-property <project> <url> # set GSC property URL
186
+ canonry google set-sitemap <project> <url> # set sitemap URL
187
+ canonry google list-sitemaps <project> # list submitted sitemaps
188
+ canonry google discover-sitemaps <project> --wait # auto-discover and inspect
189
+
190
+ canonry google sync <project> # sync GSC data
191
+ canonry google sync <project> --days 30 --full --wait # full sync with wait
192
+
193
+ canonry google coverage <project> # index coverage summary
194
+ canonry google refresh <project> # force-fetch fresh GSC coverage data
195
+ canonry google performance <project> # search performance data
196
+ canonry google performance <project> --days 30 --keyword "term" --page "/url"
197
+
198
+ canonry google inspect <project> <url> # inspect specific URL
199
+ canonry google inspect-sitemap <project> --wait # bulk inspect all sitemap URLs
200
+ canonry google inspections <project> # inspection history
201
+ canonry google inspections <project> --url <url> # filter by URL
202
+ canonry google deindexed <project> # pages that lost indexing
203
+
204
+ canonry google request-indexing <project> <url> # push URL to Google
205
+ canonry google request-indexing <project> --all-unindexed # push all unknown pages
206
+ ```
207
+
208
+ ## Bing Webmaster Tools
209
+
210
+ ```bash
211
+ canonry bing connect <project> --api-key <key> # connect Bing WMT
212
+ canonry bing disconnect <project> # disconnect
213
+ canonry bing status <project> # connection status
214
+ canonry bing sites <project> # list verified sites
215
+ canonry bing set-site <project> <url> # set active site URL
216
+ canonry bing coverage <project> # URL coverage data
217
+ canonry bing refresh <project> # force-fetch fresh Bing coverage data
218
+ canonry bing inspect <project> <url> # inspect specific URL
219
+ canonry bing inspections <project> # inspection history
220
+ canonry bing request-indexing <project> <url> # submit URL for indexing
221
+ canonry bing request-indexing <project> --all-unindexed # submit all unindexed
222
+ canonry bing performance <project> # search performance data
223
+ ```
224
+
225
+ ## WordPress Integration
226
+
227
+ ```bash
228
+ canonry wordpress connect <project> --url <url> --user <user> # connect (prompts for app password)
229
+ canonry wordpress disconnect <project> # disconnect
230
+ canonry wordpress status <project> # connection status
231
+ canonry wordpress pages <project> [--live|--staging] # list pages
232
+ canonry wordpress page <project> <slug> # show page detail
233
+ canonry wordpress create-page <project> --title <t> --slug <s> --content <c> # create page
234
+ canonry wordpress update-page <project> <slug> --content <c> # update page
235
+ canonry wordpress set-meta <project> <slug> --title <t> # set SEO meta (single page)
236
+ canonry wordpress set-meta <project> --from <file> # bulk set SEO meta from JSON
237
+ canonry wordpress schema <project> <slug> # read page JSON-LD
238
+ canonry wordpress schema deploy <project> --profile <file> # deploy schema from profile
239
+ canonry wordpress schema status <project> # schema status per page
240
+ canonry wordpress set-schema <project> <slug> # manual schema handoff
241
+ canonry wordpress audit <project> # audit pages for SEO issues
242
+ canonry wordpress diff <project> <slug> # compare live vs staging
243
+ canonry wordpress staging status <project> # staging config status
244
+ canonry wordpress staging push <project> # manual staging push handoff
245
+ canonry wordpress llms-txt <project> # read /llms.txt
246
+ canonry wordpress set-llms-txt <project> # manual llms.txt handoff
247
+ canonry wordpress onboard <project> --url <url> --user <user> # full onboarding workflow
248
+ ```
249
+
250
+ **Onboard** runs: connect → audit → set-meta → schema deploy → Google submit → Bing submit. Use `--skip-schema` or `--skip-submit` to skip steps. `--profile <file>` provides business data and page-to-schema mapping for schema deployment.
251
+
252
+ ## Google Analytics 4
253
+
254
+ GA4 integration uses service account authentication (no OAuth). The service account must have Viewer access on the GA4 property.
255
+
256
+ ```bash
257
+ canonry ga connect <project> --property-id <id> --key-file ./sa-key.json # connect GA4
258
+ canonry ga disconnect <project> # disconnect
259
+ canonry ga status <project> # connection status
260
+ canonry ga sync <project> [--days 30] [--only traffic|ai|social] # pull GA4 data (selective or full)
261
+ canonry ga traffic <project> # landing pages + AI/social referral sources
262
+ canonry ga coverage <project> # indexed pages with traffic overlay
263
+ canonry ga ai-referral-history <project> # daily AI referral history by source
264
+ canonry ga social-referral-history <project> # daily social referral history by source
265
+ canonry ga social-referral-summary <project> [--trend] # one-line social summary + optional trend
266
+ canonry ga attribution <project> [--trend] # unified channel attribution overview + optional trends
267
+ ```
268
+
269
+ ## CDP / Browser Provider
270
+
271
+ The CDP (Chrome DevTools Protocol) provider enables browser-based queries against AI chat interfaces (e.g., ChatGPT). This gives more accurate results than API-based providers for some use cases.
272
+
273
+ ```bash
274
+ canonry cdp connect --host localhost --port 9222 # connect to Chrome CDP
275
+ canonry cdp status # show connection status
276
+ canonry cdp targets # list available targets (ChatGPT, etc.)
277
+ canonry cdp screenshot <query> --targets chatgpt # screenshot a query result
278
+ ```
279
+
280
+ **Requires:** Chrome running with `--remote-debugging-port=9222`
281
+
282
+ ## Telemetry
283
+
284
+ ```bash
285
+ canonry telemetry status # show telemetry status
286
+ canonry telemetry enable # enable anonymous telemetry
287
+ canonry telemetry disable # disable telemetry
288
+ ```
289
+
290
+ ## Config as Code
291
+
292
+ ```bash
293
+ canonry apply project.yaml # apply declarative config
294
+ canonry apply file1.yaml file2.yaml # multiple files
295
+ canonry export <project> --include-results > project.yaml
296
+ canonry sitemap inspect <project>
297
+ ```
298
+
299
+ ## Agent (OpenClaw Integration)
300
+
301
+ `canonry agent setup` is the single entry point for configuring the agent. It handles everything:
302
+ canonry initialization, OpenClaw installation, profile setup, LLM credential configuration,
303
+ and workspace seeding. If canonry is not yet configured, it runs the interactive init flow first
304
+ (prompting for monitoring provider keys and agent LLM credentials).
305
+
306
+ ```bash
307
+ # Full setup (interactive — prompts for provider keys + agent LLM)
308
+ canonry agent setup
309
+
310
+ # Non-interactive (flags or env vars)
311
+ canonry agent setup --gemini-key <key> --agent-key <key>
312
+ canonry agent setup --agent-provider openrouter --agent-key <key> --agent-model openrouter/anthropic/claude-sonnet-4-6
313
+ GEMINI_API_KEY=<key> canonry agent setup --agent-key <key> --format json
314
+
315
+ # Lifecycle
316
+ canonry agent start # start OpenClaw gateway as background process
317
+ canonry agent stop # stop the gateway process
318
+ canonry agent status # check if gateway is running
319
+ canonry agent status --format json # JSON output
320
+ canonry agent reset # stop gateway and wipe workspace
321
+
322
+ # Setup flags
323
+ canonry agent setup --agent-provider <id> # LLM provider (default: anthropic)
324
+ canonry agent setup --agent-key <key> # API key for agent LLM
325
+ canonry agent setup --agent-model <model> # model id (e.g. anthropic/claude-sonnet-4-6)
326
+ canonry agent setup --gateway-port 3579 # gateway WebSocket port
327
+ canonry agent setup --gemini-key <key> # monitoring provider keys (passed to init)
328
+ canonry agent setup --openai-key <key>
329
+ canonry agent setup --claude-key <key>
330
+ canonry agent setup --perplexity-key <key>
331
+
332
+ # Webhook lifecycle
333
+ canonry agent attach <project> # register agent webhook for project
334
+ canonry agent attach <project> --format json # JSON output
335
+ canonry agent detach <project> # remove agent webhook from project
336
+ canonry agent detach <project> --format json # JSON output
337
+ ```
338
+
339
+ **Setup flow:** init canonry (if needed) → install OpenClaw (if needed) → configure profile → configure gateway → set agent LLM credentials → seed workspace with skills.
340
+
341
+ **Agent LLM credentials** are stored in `~/.openclaw-aero/.env` (e.g. `ANTHROPIC_API_KEY=...`) and loaded into the gateway process at start time. The model is set via `openclaw models set`.
342
+
343
+ **Re-running is safe:** setup is idempotent — it skips steps that are already configured.
344
+
345
+ **Agent webhooks:** `canonry agent attach <project>` registers a webhook notification on the project so the agent receives events (`run.completed`, `insight.critical`, `insight.high`, `citation.gained`). Idempotent — skips if an agent webhook already exists. `canonry agent detach <project>` removes the agent webhook. When `autoStart` is enabled, the server auto-attaches webhooks to newly created or applied projects.
346
+
347
+ ## Output Formats
348
+
349
+ Most commands support `--format json` for machine-readable output.
@@ -0,0 +1,155 @@
1
+ # Indexing Workflows for AEO
2
+
3
+ Getting pages indexed fast is high-leverage AEO work. Unindexed pages are invisible to AI citation regardless of content quality.
4
+
5
+ ## Priority Order
6
+
7
+ 1. **Google Indexing API** — fastest path to ChatGPT/Perplexity visibility (they lean on Google)
8
+ 2. **Bing WMT + IndexNow** — fastest path to Copilot/Bing AI visibility
9
+ 3. **Sitemap submission** — baseline for both; do once on setup
10
+
11
+ ---
12
+
13
+ ## Google Search Console
14
+
15
+ ### Check coverage
16
+ ```bash
17
+ canonry google coverage <project>
18
+ ```
19
+
20
+ Statuses to act on:
21
+ - `URL is unknown to Google` → highest priority, submit immediately
22
+ - `Discovered - currently not indexed` → Google found it but hasn't crawled — submit to accelerate
23
+ - `indexed` → no action needed
24
+
25
+ ### Sync GSC data
26
+ ```bash
27
+ canonry google sync <project> # incremental sync
28
+ canonry google sync <project> --full --wait # full re-sync
29
+ ```
30
+
31
+ ### Check search performance
32
+ ```bash
33
+ canonry google performance <project> # default 28 days
34
+ canonry google performance <project> --days 90 --keyword "term"
35
+ ```
36
+
37
+ ### Discover and inspect sitemaps
38
+ ```bash
39
+ canonry google discover-sitemaps <project> --wait # auto-discover sitemaps and queue inspection
40
+ canonry google list-sitemaps <project> # list submitted sitemaps
41
+ canonry google inspect-sitemap <project> --wait # bulk inspect all sitemap URLs
42
+ ```
43
+
44
+ ### Inspect individual URLs
45
+ ```bash
46
+ canonry google inspect <project> <url> # inspect specific URL
47
+ canonry google inspections <project> # inspection history
48
+ canonry google inspections <project> --url <url> # filter by URL
49
+ canonry google deindexed <project> # pages that lost indexing
50
+ ```
51
+
52
+ ### Submit URLs to Google Indexing API
53
+ ```bash
54
+ # Single URL
55
+ canonry google request-indexing <project> <url>
56
+
57
+ # All unindexed at once
58
+ canonry google request-indexing <project> --all-unindexed
59
+ ```
60
+
61
+ **Requirements:**
62
+ - "Web Search Indexing API" enabled in the GCP project
63
+ - OAuth connection set up in canonry (`canonry settings` shows Google connection)
64
+ - Officially intended for JobPosting/BroadcastEvent schema; in practice Google processes all URLs
65
+
66
+ **After submitting:** Check coverage again after 48h. Once indexed, run a sweep — pages must be indexed before citation is possible.
67
+
68
+ ---
69
+
70
+ ## Bing Webmaster Tools
71
+
72
+ ### One-time setup
73
+ ```bash
74
+ canonry bing connect <project> --api-key <key>
75
+ canonry bing set-site <project> https://example.com/
76
+ ```
77
+
78
+ Get API key from: https://www.bing.com/webmasters/ → Settings → API Access
79
+
80
+ ### Check connection and coverage
81
+ ```bash
82
+ canonry bing status <project>
83
+ canonry bing coverage <project>
84
+ canonry bing performance <project>
85
+ ```
86
+
87
+ ### Inspect URLs
88
+ ```bash
89
+ canonry bing inspect <project> <url>
90
+ canonry bing inspections <project>
91
+ ```
92
+
93
+ ### Submit URLs for indexing
94
+ ```bash
95
+ canonry bing request-indexing <project> <url>
96
+ canonry bing request-indexing <project> --all-unindexed
97
+ ```
98
+
99
+ ### Submit sitemap (manual, one-time)
100
+ Bing WMT → Sitemaps → submit `https://example.com/sitemap.xml`
101
+
102
+ ### IndexNow (instant crawl signal)
103
+ IndexNow is a direct ping to Bing: "these URLs changed, crawl them now." Without it, Bing discovers pages on its own schedule (days to weeks). With it, typically hours.
104
+
105
+ **Host the key file at the root:**
106
+ ```
107
+ https://example.com/<key>.txt
108
+ ```
109
+ File content: just the key string, nothing else.
110
+
111
+ **Submit URLs:**
112
+ ```bash
113
+ curl -X POST "https://www.bing.com/indexnow" \
114
+ -H "Content-Type: application/json; charset=utf-8" \
115
+ -d '{
116
+ "host": "example.com",
117
+ "key": "<key>",
118
+ "keyLocation": "https://example.com/<key>.txt",
119
+ "urlList": [
120
+ "https://example.com/",
121
+ "https://example.com/page-1"
122
+ ]
123
+ }'
124
+ ```
125
+
126
+ Expected response: `202 Accepted`
127
+
128
+ **Note:** IndexNow only covers Bing (and Yandex). It does NOT affect ChatGPT, Claude, or Gemini.
129
+
130
+ ---
131
+
132
+ ## When to Use What
133
+
134
+ | Goal | Tool |
135
+ |---|---|
136
+ | Get pages into ChatGPT / Perplexity / Claude | Google Indexing API |
137
+ | Get pages into Copilot / Bing AI | IndexNow + Bing WMT |
138
+ | Audit what Google currently knows | `canonry google coverage <project>` |
139
+ | Audit what Bing currently knows | `canonry bing coverage <project>` |
140
+ | Fast crawl of new/updated pages on Bing | IndexNow batch submit |
141
+ | Ongoing Google crawl health | `canonry google sync` + `canonry google performance` |
142
+ | Ongoing Bing crawl health | Bing WMT sitemap + `canonry bing performance` |
143
+ | Find deindexed pages | `canonry google deindexed <project>` |
144
+
145
+ ---
146
+
147
+ ## General Workflow for New Client Pages
148
+
149
+ 1. `canonry google coverage <project>` — identify unindexed pages
150
+ 2. `canonry google request-indexing <project> --all-unindexed` — push to Google
151
+ 3. `canonry bing request-indexing <project> --all-unindexed` — push to Bing
152
+ 4. Submit sitemap to Bing WMT (manual, one-time per site)
153
+ 5. Send IndexNow batch for key URLs
154
+ 6. Re-check coverage after 48h
155
+ 7. Run a sweep after pages confirmed indexed