@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.
- package/README.md +93 -441
- package/assets/agent-workspace/AGENTS.md +89 -0
- package/assets/agent-workspace/SOUL.md +54 -0
- package/assets/agent-workspace/USER.md +23 -0
- package/assets/agent-workspace/skills/aero/SKILL.md +42 -0
- package/assets/agent-workspace/skills/aero/references/memory-patterns.md +37 -0
- package/assets/agent-workspace/skills/aero/references/orchestration.md +52 -0
- package/assets/agent-workspace/skills/aero/references/regression-playbook.md +34 -0
- package/assets/agent-workspace/skills/aero/references/reporting.md +67 -0
- package/assets/agent-workspace/skills/canonry-setup/SKILL.md +274 -0
- package/assets/agent-workspace/skills/canonry-setup/references/aeo-analysis.md +130 -0
- package/assets/agent-workspace/skills/canonry-setup/references/canonry-cli.md +349 -0
- package/assets/agent-workspace/skills/canonry-setup/references/indexing.md +155 -0
- package/assets/agent-workspace/skills/canonry-setup/references/wordpress-integration.md +57 -0
- package/assets/assets/{index-Cxg_4UWs.js → index-CVk23m8J.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-22RIKNII.js → chunk-25QLMK4F.js} +803 -138
- package/dist/cli.js +457 -87
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1 -1
- package/package.json +7 -7
|
@@ -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
|