@canonry/canonry 7.62.0 → 7.62.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/agent-workspace/skills/aero/SKILL.md +7 -0
- package/assets/agent-workspace/skills/aero/references/ai-traffic-tracking.md +152 -0
- package/assets/agent-workspace/skills/canonry/SKILL.md +1 -0
- package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +145 -0
- package/dist/{chunk-GMP7OZDW.js → chunk-I3CMCTNE.js} +1 -1
- package/dist/{chunk-3NICRFTU.js → chunk-LFXKB5FZ.js} +3 -3
- package/dist/{chunk-YQMQWDTI.js → chunk-O6VSPM5S.js} +1 -1
- package/dist/{cli-commands-4YSZAPKZ.js → cli-commands-VSS42S5I.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +66 -66
- package/dist/index.js +1 -1
- package/dist/{init-4YT2HMKY.js → init-VJDDRCBV.js} +1 -1
- package/dist/{serve-5A4K242B.js → serve-OCAFOFS2.js} +1 -1
- package/package.json +1 -1
|
@@ -183,6 +183,12 @@ Get approval before you run a manual sync or change the schedule. The full
|
|
|
183
183
|
command reference is in the co-installed
|
|
184
184
|
`canonry/references/canonry-cli.md`.
|
|
185
185
|
|
|
186
|
+
When someone asks whether AI search sent visitors, whether they came back, or
|
|
187
|
+
whether they bought, booked or became leads, read `references/ai-traffic-tracking.md`
|
|
188
|
+
first. Report crawled, read, clicked, came back and converted as separate
|
|
189
|
+
numbers, and never report zero conversions until you have checked that the
|
|
190
|
+
conversion is tracked and reaches GA4.
|
|
191
|
+
|
|
186
192
|
**Diagnosing a stuck Vercel/Cloud Run source:** if `cnry traffic status` shows `status=error` with a recent `lastError` of `refusing to advance` or `ExceedsBillingLimitError`, the source's `lastSyncedAt` has aged past the upstream retention boundary and every sync now throws. Recovery: `cnry traffic reset <project> --source <id> --advance-to-now`. This advances `lastSyncedAt` to NOW and resumes going-forward syncs — historical events in the gap are unrecoverable from the sync path; run `cnry traffic backfill --days N` separately if any of that history is needed (capped at retention).
|
|
187
193
|
|
|
188
194
|
## Judgment Rules
|
|
@@ -260,6 +266,7 @@ Detailed playbooks live alongside this file. Read them on demand when the task m
|
|
|
260
266
|
| `references/aeo-discovery.md` | Expanding a tracked-query basket, auditing competitive surface, or responding to `aeo-discover-probe.completed` |
|
|
261
267
|
| `references/memory-patterns.md` | Deciding whether to remember a fact in agent memory or re-query canonry |
|
|
262
268
|
| `references/reporting.md` | Producing a client-facing weekly or monthly summary |
|
|
269
|
+
| `references/ai-traffic-tracking.md` | Answering whether AI traffic led to visits, return visits, leads, bookings or sales, or whether tracking is broken; generated from the Canonry reference |
|
|
263
270
|
| `references/wordpress-elementor-mcp.md` | Editing WordPress pages with the Elementor MCP integration |
|
|
264
271
|
|
|
265
272
|
Aero (canonry's built-in agent) exposes `list_skill_docs` / `read_skill_doc` tools that walk this directory programmatically. External agents (Claude Code, Codex) can read the files directly.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ai-traffic-tracking
|
|
3
|
+
description: "Crawled, read, clicked, came back, converted: which instrument measures each step, the checks to run before reporting a zero, attribution limits, and user stories such as whether anyone from AI search bought or booked. Read when asked about AI traffic, returning AI visitors, conversions, or broken tracking."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- Generated from skills/canonry/references/ai-traffic-tracking.md by pnpm guide:sync. Do not edit. -->
|
|
7
|
+
|
|
8
|
+
# Tracking AI traffic to visits and conversions
|
|
9
|
+
|
|
10
|
+
Read this before you answer whether AI search sent visitors, whether those
|
|
11
|
+
visitors came back, or whether they bought, booked or became leads. Read it too
|
|
12
|
+
when someone says "our tracking is broken" or "AI referrals dropped".
|
|
13
|
+
|
|
14
|
+
Everything here is a stored read unless it says otherwise. Changing a setting,
|
|
15
|
+
connecting a source, a backfill or a GA sync each need approval for that exact
|
|
16
|
+
action.
|
|
17
|
+
|
|
18
|
+
## The funnel and what measures each step
|
|
19
|
+
|
|
20
|
+
Each step is usually 10 to 100 times smaller than the one above it. Most AI
|
|
21
|
+
answers are read inside the assistant, so a site can be read often and clicked
|
|
22
|
+
rarely. Report every step separately; never pool them.
|
|
23
|
+
|
|
24
|
+
| Step | What it is | Instrument | Read with |
|
|
25
|
+
|---|---|---|---|
|
|
26
|
+
| Crawled | AI and search bots fetch pages to index them | Server-side traffic, `crawler` | `cnry traffic events <p> --kind crawler` (`canonry_traffic_events`) |
|
|
27
|
+
| Read for a user | An assistant fetches a page live while answering someone (ChatGPT-User, Claude-User, Perplexity-User) | Server-side traffic, `ai-user-fetch` | `cnry traffic events <p> --kind ai-user-fetch` |
|
|
28
|
+
| Clicked | A person follows a link from an AI answer | Server-side `ai-referral` hits; GA4 AI sessions | `cnry traffic events <p> --kind ai-referral`; `cnry ga ai-referral-history <p>` (`canonry_ga_ai_referral_history`) |
|
|
29
|
+
| Came back | That person's later visits, from any channel | AI visitor journeys (server logs) | `cnry journeys summary\|list\|show <p>` (`canonry_journeys_summary`, `canonry_journeys_list`, `canonry_journey_get`) |
|
|
30
|
+
| Converted | Lead, booking or purchase | GA4 events named in `measurement.leadEventNames` | `cnry ga measurement-analysis <p> --window 90d --host-scope all` (`canonry_ga_measurement_analysis`) |
|
|
31
|
+
|
|
32
|
+
Server-side hits are requests and GA4 counts sessions, and each instrument
|
|
33
|
+
misses some visits the other sees, so the two never match exactly. Compare
|
|
34
|
+
their trend, not their totals.
|
|
35
|
+
|
|
36
|
+
## Check the instrument before you report a zero
|
|
37
|
+
|
|
38
|
+
A zero means nothing until you know the instrument could have seen it. Work
|
|
39
|
+
through these in order and say which one applies.
|
|
40
|
+
|
|
41
|
+
1. **Is the conversion tracked at all?** Read the project's
|
|
42
|
+
`measurement.leadEventNames` (`cnry project show <p> --format json`). The
|
|
43
|
+
default is only `generate_lead`. Online stores report sales as `purchase`,
|
|
44
|
+
and booking engines often do too. If lead events are zero across every
|
|
45
|
+
channel, not only AI, the instrument is blind: report "conversions are not
|
|
46
|
+
measured", never "AI drove no conversions". Adding an event is a setting
|
|
47
|
+
change (`cnry project update <p> --add-lead-event purchase`) and needs
|
|
48
|
+
approval; the daily refresh then fills about 30 days.
|
|
49
|
+
2. **Does GA4 receive the event?** Read the stored GTM snapshot
|
|
50
|
+
(`cnry gtm snapshots <p>`, then `cnry gtm snapshot <p> <id>`;
|
|
51
|
+
`canonry_gtm_snapshot_get`). If the booking or purchase trigger fires only
|
|
52
|
+
Google Ads tags (`awct`) and no GA4 event tag, GA4 records no conversions.
|
|
53
|
+
The fix is a GA4 Event tag on the same trigger, made by someone with
|
|
54
|
+
publish rights in the site's GTM container. Canonry's GTM access is
|
|
55
|
+
read-only.
|
|
56
|
+
3. **Do two instruments agree?** Compare Canonry's GA4 AI sessions with GA4's
|
|
57
|
+
own `AI Assistant` channel (`cnry ga acquisition <p> --window 30d
|
|
58
|
+
--group-by channel`), and with server-side `ai-referral` hits. Agreement
|
|
59
|
+
between independent instruments rules out an ingestion fault. GA4 may file
|
|
60
|
+
AI shopping links under another channel when they carry a different
|
|
61
|
+
`utm_medium` (for example `feed`); the source still reads `chatgpt.com`.
|
|
62
|
+
4. **Paid or organic?** An AI-referral spike can be an ads test. GA4 rows carry
|
|
63
|
+
`trafficClass`, and server-side referrals split paid from organic. Never
|
|
64
|
+
compare a paid month with organic months, and say "the ads ended" rather
|
|
65
|
+
than "AI traffic dropped" when the paid line is what fell.
|
|
66
|
+
5. **Is the source reading the right site?** Confirm the traffic source's
|
|
67
|
+
service or host actually serves the domain (for example, check which backend
|
|
68
|
+
a load balancer routes the domain to) before you claim a wiring gap.
|
|
69
|
+
6. **Is the source partial?**
|
|
70
|
+
- The default Cloudflare Worker forwards only AI-referred and bot requests,
|
|
71
|
+
so journeys miss later visits until the source is reconnected with
|
|
72
|
+
`--forward-page-views` and the Worker redeployed. Journey reads list such
|
|
73
|
+
sources in `partialSources`.
|
|
74
|
+
- The WordPress logger runs inside WordPress, so it cannot see page views a
|
|
75
|
+
cache serves before WordPress runs.
|
|
76
|
+
- Vercel logs carry no IP, so journey keys use the user agent only
|
|
77
|
+
(`keyBasis`); people with the same device and browser version merge,
|
|
78
|
+
which undercounts people and overstates return rates.
|
|
79
|
+
- A hosted checkout or booking engine on another domain is outside the
|
|
80
|
+
site's server logs.
|
|
81
|
+
7. **Is a Queue backlog hiding recent traffic?** For Cloudflare Queue pull,
|
|
82
|
+
read `cnry traffic status <p>` and the last sync's `syncSummary`
|
|
83
|
+
(`cnry runs <p> --kind traffic-sync --format json`) before quoting recent
|
|
84
|
+
days. Recent days look low while a backlog drains.
|
|
85
|
+
8. **Is it noise?** Unverified "AI user" fetches of `/.env`, admin paths or
|
|
86
|
+
404s are scanners using AI bot names. Quote verified fetches
|
|
87
|
+
(`verificationStatus: verified`) and pages that returned 200.
|
|
88
|
+
|
|
89
|
+
## What attribution can and cannot say
|
|
90
|
+
|
|
91
|
+
- GA4 credits a conversion to the session it happened in. A person who first
|
|
92
|
+
came from ChatGPT and books days later from Google counts as Google. Journeys
|
|
93
|
+
keep the earlier AI touch for 30 days, but they see a conversion only when
|
|
94
|
+
its page (for example a booking confirmation URL) appears in the server logs.
|
|
95
|
+
- A return from an outside payment or booking step can take the credit in GA4
|
|
96
|
+
unless that domain is listed under unwanted referrals in the GA4 web stream
|
|
97
|
+
settings. That is a GA4 admin change for the site owner.
|
|
98
|
+
- A visitor key is a keyed hash of IP and user agent, scoped to the project.
|
|
99
|
+
Never print or ask for visitor IPs.
|
|
100
|
+
- Since iOS 26, Safari freezes the OS version in its user agent; device labels
|
|
101
|
+
use Safari's own version instead, so treat the iOS version as approximate.
|
|
102
|
+
|
|
103
|
+
## User stories
|
|
104
|
+
|
|
105
|
+
**"Did anyone from AI search buy, book or become a lead?"**
|
|
106
|
+
1. Run the instrument checks above, steps 1 and 2 first.
|
|
107
|
+
2. If conversions are measured: `cnry ga measurement-analysis <p> --window 90d
|
|
108
|
+
--host-scope all` and read `leads.aiEngines` per engine and period. Quote
|
|
109
|
+
event counts with their sessions; the lead rate is null when the evidence is
|
|
110
|
+
mixed.
|
|
111
|
+
3. Add journeys for the cross-session view: `cnry journeys list <p> --returned
|
|
112
|
+
true`, then `show` for visitors whose later visits reach a conversion page.
|
|
113
|
+
4. Say what is unmeasured. Example: "ChatGPT sent 120 sessions in 30 days.
|
|
114
|
+
Bookings are not sent to GA4, so we cannot say how many booked."
|
|
115
|
+
|
|
116
|
+
**"A customer says they found us through ChatGPT. Can we trace them?"**
|
|
117
|
+
1. Get the date and time of their purchase, booking or form, and the device if
|
|
118
|
+
known.
|
|
119
|
+
2. `cnry journeys list <p> --engine ChatGPT --since <a few days before>` and
|
|
120
|
+
`cnry journeys show <p> <visitor-key>` for visitors active near that time.
|
|
121
|
+
3. A user-agent match is "likely", never proof, unless the key also includes
|
|
122
|
+
the IP. Reading a provider's raw logs beyond what Canonry stored is a live
|
|
123
|
+
read and needs approval.
|
|
124
|
+
|
|
125
|
+
**"AI referrals dropped. Is our tracking broken?"**
|
|
126
|
+
1. Pull the monthly series from both instruments (server-side `ai-referral` and
|
|
127
|
+
GA4 AI sessions) and split paid from organic.
|
|
128
|
+
2. If both fell together, the traffic changed, not the tracking. Check for an
|
|
129
|
+
ended ads test, a lost citation or mention (`references/aeo-analysis.md`), or
|
|
130
|
+
a site change.
|
|
131
|
+
3. If only one fell, check that instrument: sync errors and stop reasons
|
|
132
|
+
(`cnry traffic status`, `cnry runs <p> --kind traffic-sync`), the GA4 tag,
|
|
133
|
+
or the source's service or host.
|
|
134
|
+
|
|
135
|
+
**"Which of our pages does AI read?"**
|
|
136
|
+
`cnry traffic events <p> --kind ai-user-fetch --since <date>`: keep verified
|
|
137
|
+
fetches with status 200, group by path, and leave out `robots.txt`. These are
|
|
138
|
+
the pages assistants open while answering people, even when nobody clicks.
|
|
139
|
+
|
|
140
|
+
**"Do AI visitors come back?"**
|
|
141
|
+
`cnry journeys summary <p>`: `returnRate`, `returnedVia` and
|
|
142
|
+
`medianDaysToReturn`. Report `keyBasis` and `partialSources` with the numbers;
|
|
143
|
+
a user-agent-only or partial source changes what the rate means.
|
|
144
|
+
|
|
145
|
+
## Reporting language
|
|
146
|
+
|
|
147
|
+
- Lead with the step, the count and the window: "Assistants read the site 300
|
|
148
|
+
times in 30 days (verified); 10 people clicked through; conversions are not
|
|
149
|
+
measured."
|
|
150
|
+
- Keep crawled, read, clicked, came back and converted as separate numbers.
|
|
151
|
+
- Name the blind spot whenever a number is zero or low because an instrument
|
|
152
|
+
cannot see it.
|
|
@@ -258,3 +258,4 @@ Read only references relevant to the requested task. They are not required for M
|
|
|
258
258
|
- [Server-side traffic setup and diagnosis](references/server-side-traffic.md)
|
|
259
259
|
- [Google Business Profile prerequisites](references/google-business-profile.md)
|
|
260
260
|
- [Google Ads and GTM evidence boundaries](references/google-marketing.md)
|
|
261
|
+
- [Tracking AI traffic to visits and conversions](references/ai-traffic-tracking.md)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Tracking AI traffic to visits and conversions
|
|
2
|
+
|
|
3
|
+
Read this before you answer whether AI search sent visitors, whether those
|
|
4
|
+
visitors came back, or whether they bought, booked or became leads. Read it too
|
|
5
|
+
when someone says "our tracking is broken" or "AI referrals dropped".
|
|
6
|
+
|
|
7
|
+
Everything here is a stored read unless it says otherwise. Changing a setting,
|
|
8
|
+
connecting a source, a backfill or a GA sync each need approval for that exact
|
|
9
|
+
action.
|
|
10
|
+
|
|
11
|
+
## The funnel and what measures each step
|
|
12
|
+
|
|
13
|
+
Each step is usually 10 to 100 times smaller than the one above it. Most AI
|
|
14
|
+
answers are read inside the assistant, so a site can be read often and clicked
|
|
15
|
+
rarely. Report every step separately; never pool them.
|
|
16
|
+
|
|
17
|
+
| Step | What it is | Instrument | Read with |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| Crawled | AI and search bots fetch pages to index them | Server-side traffic, `crawler` | `cnry traffic events <p> --kind crawler` (`canonry_traffic_events`) |
|
|
20
|
+
| Read for a user | An assistant fetches a page live while answering someone (ChatGPT-User, Claude-User, Perplexity-User) | Server-side traffic, `ai-user-fetch` | `cnry traffic events <p> --kind ai-user-fetch` |
|
|
21
|
+
| Clicked | A person follows a link from an AI answer | Server-side `ai-referral` hits; GA4 AI sessions | `cnry traffic events <p> --kind ai-referral`; `cnry ga ai-referral-history <p>` (`canonry_ga_ai_referral_history`) |
|
|
22
|
+
| Came back | That person's later visits, from any channel | AI visitor journeys (server logs) | `cnry journeys summary\|list\|show <p>` (`canonry_journeys_summary`, `canonry_journeys_list`, `canonry_journey_get`) |
|
|
23
|
+
| Converted | Lead, booking or purchase | GA4 events named in `measurement.leadEventNames` | `cnry ga measurement-analysis <p> --window 90d --host-scope all` (`canonry_ga_measurement_analysis`) |
|
|
24
|
+
|
|
25
|
+
Server-side hits are requests and GA4 counts sessions, and each instrument
|
|
26
|
+
misses some visits the other sees, so the two never match exactly. Compare
|
|
27
|
+
their trend, not their totals.
|
|
28
|
+
|
|
29
|
+
## Check the instrument before you report a zero
|
|
30
|
+
|
|
31
|
+
A zero means nothing until you know the instrument could have seen it. Work
|
|
32
|
+
through these in order and say which one applies.
|
|
33
|
+
|
|
34
|
+
1. **Is the conversion tracked at all?** Read the project's
|
|
35
|
+
`measurement.leadEventNames` (`cnry project show <p> --format json`). The
|
|
36
|
+
default is only `generate_lead`. Online stores report sales as `purchase`,
|
|
37
|
+
and booking engines often do too. If lead events are zero across every
|
|
38
|
+
channel, not only AI, the instrument is blind: report "conversions are not
|
|
39
|
+
measured", never "AI drove no conversions". Adding an event is a setting
|
|
40
|
+
change (`cnry project update <p> --add-lead-event purchase`) and needs
|
|
41
|
+
approval; the daily refresh then fills about 30 days.
|
|
42
|
+
2. **Does GA4 receive the event?** Read the stored GTM snapshot
|
|
43
|
+
(`cnry gtm snapshots <p>`, then `cnry gtm snapshot <p> <id>`;
|
|
44
|
+
`canonry_gtm_snapshot_get`). If the booking or purchase trigger fires only
|
|
45
|
+
Google Ads tags (`awct`) and no GA4 event tag, GA4 records no conversions.
|
|
46
|
+
The fix is a GA4 Event tag on the same trigger, made by someone with
|
|
47
|
+
publish rights in the site's GTM container. Canonry's GTM access is
|
|
48
|
+
read-only.
|
|
49
|
+
3. **Do two instruments agree?** Compare Canonry's GA4 AI sessions with GA4's
|
|
50
|
+
own `AI Assistant` channel (`cnry ga acquisition <p> --window 30d
|
|
51
|
+
--group-by channel`), and with server-side `ai-referral` hits. Agreement
|
|
52
|
+
between independent instruments rules out an ingestion fault. GA4 may file
|
|
53
|
+
AI shopping links under another channel when they carry a different
|
|
54
|
+
`utm_medium` (for example `feed`); the source still reads `chatgpt.com`.
|
|
55
|
+
4. **Paid or organic?** An AI-referral spike can be an ads test. GA4 rows carry
|
|
56
|
+
`trafficClass`, and server-side referrals split paid from organic. Never
|
|
57
|
+
compare a paid month with organic months, and say "the ads ended" rather
|
|
58
|
+
than "AI traffic dropped" when the paid line is what fell.
|
|
59
|
+
5. **Is the source reading the right site?** Confirm the traffic source's
|
|
60
|
+
service or host actually serves the domain (for example, check which backend
|
|
61
|
+
a load balancer routes the domain to) before you claim a wiring gap.
|
|
62
|
+
6. **Is the source partial?**
|
|
63
|
+
- The default Cloudflare Worker forwards only AI-referred and bot requests,
|
|
64
|
+
so journeys miss later visits until the source is reconnected with
|
|
65
|
+
`--forward-page-views` and the Worker redeployed. Journey reads list such
|
|
66
|
+
sources in `partialSources`.
|
|
67
|
+
- The WordPress logger runs inside WordPress, so it cannot see page views a
|
|
68
|
+
cache serves before WordPress runs.
|
|
69
|
+
- Vercel logs carry no IP, so journey keys use the user agent only
|
|
70
|
+
(`keyBasis`); people with the same device and browser version merge,
|
|
71
|
+
which undercounts people and overstates return rates.
|
|
72
|
+
- A hosted checkout or booking engine on another domain is outside the
|
|
73
|
+
site's server logs.
|
|
74
|
+
7. **Is a Queue backlog hiding recent traffic?** For Cloudflare Queue pull,
|
|
75
|
+
read `cnry traffic status <p>` and the last sync's `syncSummary`
|
|
76
|
+
(`cnry runs <p> --kind traffic-sync --format json`) before quoting recent
|
|
77
|
+
days. Recent days look low while a backlog drains.
|
|
78
|
+
8. **Is it noise?** Unverified "AI user" fetches of `/.env`, admin paths or
|
|
79
|
+
404s are scanners using AI bot names. Quote verified fetches
|
|
80
|
+
(`verificationStatus: verified`) and pages that returned 200.
|
|
81
|
+
|
|
82
|
+
## What attribution can and cannot say
|
|
83
|
+
|
|
84
|
+
- GA4 credits a conversion to the session it happened in. A person who first
|
|
85
|
+
came from ChatGPT and books days later from Google counts as Google. Journeys
|
|
86
|
+
keep the earlier AI touch for 30 days, but they see a conversion only when
|
|
87
|
+
its page (for example a booking confirmation URL) appears in the server logs.
|
|
88
|
+
- A return from an outside payment or booking step can take the credit in GA4
|
|
89
|
+
unless that domain is listed under unwanted referrals in the GA4 web stream
|
|
90
|
+
settings. That is a GA4 admin change for the site owner.
|
|
91
|
+
- A visitor key is a keyed hash of IP and user agent, scoped to the project.
|
|
92
|
+
Never print or ask for visitor IPs.
|
|
93
|
+
- Since iOS 26, Safari freezes the OS version in its user agent; device labels
|
|
94
|
+
use Safari's own version instead, so treat the iOS version as approximate.
|
|
95
|
+
|
|
96
|
+
## User stories
|
|
97
|
+
|
|
98
|
+
**"Did anyone from AI search buy, book or become a lead?"**
|
|
99
|
+
1. Run the instrument checks above, steps 1 and 2 first.
|
|
100
|
+
2. If conversions are measured: `cnry ga measurement-analysis <p> --window 90d
|
|
101
|
+
--host-scope all` and read `leads.aiEngines` per engine and period. Quote
|
|
102
|
+
event counts with their sessions; the lead rate is null when the evidence is
|
|
103
|
+
mixed.
|
|
104
|
+
3. Add journeys for the cross-session view: `cnry journeys list <p> --returned
|
|
105
|
+
true`, then `show` for visitors whose later visits reach a conversion page.
|
|
106
|
+
4. Say what is unmeasured. Example: "ChatGPT sent 120 sessions in 30 days.
|
|
107
|
+
Bookings are not sent to GA4, so we cannot say how many booked."
|
|
108
|
+
|
|
109
|
+
**"A customer says they found us through ChatGPT. Can we trace them?"**
|
|
110
|
+
1. Get the date and time of their purchase, booking or form, and the device if
|
|
111
|
+
known.
|
|
112
|
+
2. `cnry journeys list <p> --engine ChatGPT --since <a few days before>` and
|
|
113
|
+
`cnry journeys show <p> <visitor-key>` for visitors active near that time.
|
|
114
|
+
3. A user-agent match is "likely", never proof, unless the key also includes
|
|
115
|
+
the IP. Reading a provider's raw logs beyond what Canonry stored is a live
|
|
116
|
+
read and needs approval.
|
|
117
|
+
|
|
118
|
+
**"AI referrals dropped. Is our tracking broken?"**
|
|
119
|
+
1. Pull the monthly series from both instruments (server-side `ai-referral` and
|
|
120
|
+
GA4 AI sessions) and split paid from organic.
|
|
121
|
+
2. If both fell together, the traffic changed, not the tracking. Check for an
|
|
122
|
+
ended ads test, a lost citation or mention (`references/aeo-analysis.md`), or
|
|
123
|
+
a site change.
|
|
124
|
+
3. If only one fell, check that instrument: sync errors and stop reasons
|
|
125
|
+
(`cnry traffic status`, `cnry runs <p> --kind traffic-sync`), the GA4 tag,
|
|
126
|
+
or the source's service or host.
|
|
127
|
+
|
|
128
|
+
**"Which of our pages does AI read?"**
|
|
129
|
+
`cnry traffic events <p> --kind ai-user-fetch --since <date>`: keep verified
|
|
130
|
+
fetches with status 200, group by path, and leave out `robots.txt`. These are
|
|
131
|
+
the pages assistants open while answering people, even when nobody clicks.
|
|
132
|
+
|
|
133
|
+
**"Do AI visitors come back?"**
|
|
134
|
+
`cnry journeys summary <p>`: `returnRate`, `returnedVia` and
|
|
135
|
+
`medianDaysToReturn`. Report `keyBasis` and `partialSources` with the numbers;
|
|
136
|
+
a user-agent-only or partial source changes what the rate means.
|
|
137
|
+
|
|
138
|
+
## Reporting language
|
|
139
|
+
|
|
140
|
+
- Lead with the step, the count and the window: "Assistants read the site 300
|
|
141
|
+
times in 30 days (verified); 10 people clicked through; conversions are not
|
|
142
|
+
measured."
|
|
143
|
+
- Keep crawled, read, clicked, came back and converted as separate numbers.
|
|
144
|
+
- Name the blind spot whenever a number is zero or low because an instrument
|
|
145
|
+
cannot see it.
|
|
@@ -47,7 +47,7 @@ function queueServeHandoff() {
|
|
|
47
47
|
async function runPendingServeHandoff(format) {
|
|
48
48
|
if (!pendingServeHandoff) return;
|
|
49
49
|
pendingServeHandoff = false;
|
|
50
|
-
const { serveCommand } = await import("./serve-
|
|
50
|
+
const { serveCommand } = await import("./serve-OCAFOFS2.js");
|
|
51
51
|
await serveCommand(format);
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -6702,7 +6702,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6702
6702
|
options: { access: stringOption() },
|
|
6703
6703
|
run: async (input) => {
|
|
6704
6704
|
if (input.positionals.length > 1) throw usageError("Expected at most one command group");
|
|
6705
|
-
const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-WOWYZ7Q2.js"), import("./cli-commands-
|
|
6705
|
+
const [{ printCliCatalog }, { REGISTERED_CLI_COMMANDS: REGISTERED_CLI_COMMANDS2 }] = await Promise.all([import("./cli-catalog-WOWYZ7Q2.js"), import("./cli-commands-VSS42S5I.js")]);
|
|
6706
6706
|
printCliCatalog(REGISTERED_CLI_COMMANDS2, input.format, input.positionals[0], getString(input.values, "access"));
|
|
6707
6707
|
}
|
|
6708
6708
|
},
|
|
@@ -6751,7 +6751,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6751
6751
|
},
|
|
6752
6752
|
allowPositionals: false,
|
|
6753
6753
|
run: async (input) => {
|
|
6754
|
-
const { initCommand } = await import("./init-
|
|
6754
|
+
const { initCommand } = await import("./init-VJDDRCBV.js");
|
|
6755
6755
|
await initCommand({
|
|
6756
6756
|
force: getBoolean(input.values, "force"),
|
|
6757
6757
|
ref: getString(input.values, "ref"),
|
|
@@ -6806,7 +6806,7 @@ var SYSTEM_CLI_COMMANDS = [
|
|
|
6806
6806
|
allowPositionals: false,
|
|
6807
6807
|
run: async (input) => {
|
|
6808
6808
|
applyServerEnv(input.values);
|
|
6809
|
-
const { serveCommand } = await import("./serve-
|
|
6809
|
+
const { serveCommand } = await import("./serve-OCAFOFS2.js");
|
|
6810
6810
|
await serveCommand(input.format);
|
|
6811
6811
|
}
|
|
6812
6812
|
},
|
|
@@ -5657,7 +5657,7 @@ function nonBlank(value) {
|
|
|
5657
5657
|
return trimmed ? trimmed : void 0;
|
|
5658
5658
|
}
|
|
5659
5659
|
function resolveBuildCommit(env = process.env) {
|
|
5660
|
-
const embedded = true ? "
|
|
5660
|
+
const embedded = true ? "6b84bb1b02f35a10a9f5acf10daf9c9e9df2a2d1" : void 0;
|
|
5661
5661
|
return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
|
|
5662
5662
|
}
|
|
5663
5663
|
function resolveInstanceIdentity(env = process.env) {
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node --import tsx
|
|
2
2
|
import {
|
|
3
3
|
REGISTERED_CLI_COMMANDS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LFXKB5FZ.js";
|
|
5
5
|
import {
|
|
6
6
|
buildSetupState,
|
|
7
7
|
runPendingServeHandoff
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-I3CMCTNE.js";
|
|
9
9
|
import "./chunk-6GO5VVAC.js";
|
|
10
10
|
import "./chunk-GSHHYR24.js";
|
|
11
11
|
import "./chunk-VJWDBFSL.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -70,10 +70,10 @@ declare const googleAdsAccessibleCustomerDtoSchema: z.ZodObject<{
|
|
|
70
70
|
level: z.ZodNumber;
|
|
71
71
|
status: z.ZodEnum<{
|
|
72
72
|
unknown: "unknown";
|
|
73
|
-
canceled: "canceled";
|
|
74
73
|
enabled: "enabled";
|
|
75
74
|
suspended: "suspended";
|
|
76
75
|
closed: "closed";
|
|
76
|
+
canceled: "canceled";
|
|
77
77
|
unspecified: "unspecified";
|
|
78
78
|
}>;
|
|
79
79
|
}, z.core.$strict>;
|
|
@@ -92,10 +92,10 @@ declare const googleAdsAccessibleCustomersResponseSchema: z.ZodObject<{
|
|
|
92
92
|
level: z.ZodNumber;
|
|
93
93
|
status: z.ZodEnum<{
|
|
94
94
|
unknown: "unknown";
|
|
95
|
-
canceled: "canceled";
|
|
96
95
|
enabled: "enabled";
|
|
97
96
|
suspended: "suspended";
|
|
98
97
|
closed: "closed";
|
|
98
|
+
canceled: "canceled";
|
|
99
99
|
unspecified: "unspecified";
|
|
100
100
|
}>;
|
|
101
101
|
}, z.core.$strict>>;
|
|
@@ -115,8 +115,8 @@ declare const googleAdsEffectiveGoalGraphDtoSchema: z.ZodObject<{
|
|
|
115
115
|
campaigns: z.ZodArray<z.ZodObject<{
|
|
116
116
|
campaignId: z.ZodString;
|
|
117
117
|
goalConfigLevel: z.ZodEnum<{
|
|
118
|
-
campaign: "campaign";
|
|
119
118
|
customer: "customer";
|
|
119
|
+
campaign: "campaign";
|
|
120
120
|
}>;
|
|
121
121
|
customGoalId: z.ZodNullable<z.ZodString>;
|
|
122
122
|
missingCustomGoalId: z.ZodNullable<z.ZodString>;
|
|
@@ -180,10 +180,10 @@ declare const googleAdsRawSnapshotDtoSchema: z.ZodObject<{
|
|
|
180
180
|
level: z.ZodNumber;
|
|
181
181
|
status: z.ZodEnum<{
|
|
182
182
|
unknown: "unknown";
|
|
183
|
-
canceled: "canceled";
|
|
184
183
|
enabled: "enabled";
|
|
185
184
|
suspended: "suspended";
|
|
186
185
|
closed: "closed";
|
|
186
|
+
canceled: "canceled";
|
|
187
187
|
unspecified: "unspecified";
|
|
188
188
|
}>;
|
|
189
189
|
}, z.core.$strict>>;
|
|
@@ -208,8 +208,8 @@ declare const googleAdsRawSnapshotDtoSchema: z.ZodObject<{
|
|
|
208
208
|
status: z.ZodEnum<{
|
|
209
209
|
unknown: "unknown";
|
|
210
210
|
enabled: "enabled";
|
|
211
|
-
paused: "paused";
|
|
212
211
|
removed: "removed";
|
|
212
|
+
paused: "paused";
|
|
213
213
|
}>;
|
|
214
214
|
advertisingChannelType: z.ZodNullable<z.ZodString>;
|
|
215
215
|
biddingStrategyType: z.ZodNullable<z.ZodString>;
|
|
@@ -221,8 +221,8 @@ declare const googleAdsRawSnapshotDtoSchema: z.ZodObject<{
|
|
|
221
221
|
status: z.ZodEnum<{
|
|
222
222
|
unknown: "unknown";
|
|
223
223
|
enabled: "enabled";
|
|
224
|
-
hidden: "hidden";
|
|
225
224
|
removed: "removed";
|
|
225
|
+
hidden: "hidden";
|
|
226
226
|
}>;
|
|
227
227
|
category: z.ZodString;
|
|
228
228
|
origin: z.ZodString;
|
|
@@ -249,8 +249,8 @@ declare const googleAdsRawSnapshotDtoSchema: z.ZodObject<{
|
|
|
249
249
|
campaignGoalConfigurations: z.ZodArray<z.ZodObject<{
|
|
250
250
|
campaignId: z.ZodString;
|
|
251
251
|
goalConfigLevel: z.ZodEnum<{
|
|
252
|
-
campaign: "campaign";
|
|
253
252
|
customer: "customer";
|
|
253
|
+
campaign: "campaign";
|
|
254
254
|
}>;
|
|
255
255
|
customGoalId: z.ZodNullable<z.ZodString>;
|
|
256
256
|
}, z.core.$strict>>;
|
|
@@ -331,9 +331,9 @@ declare const gtmRawSnapshotDtoSchema: z.ZodObject<{
|
|
|
331
331
|
connectionId: z.ZodString;
|
|
332
332
|
runId: z.ZodString;
|
|
333
333
|
kind: z.ZodEnum<{
|
|
334
|
+
live: "live";
|
|
334
335
|
accounts: "accounts";
|
|
335
336
|
container: "container";
|
|
336
|
-
live: "live";
|
|
337
337
|
draft: "draft";
|
|
338
338
|
}>;
|
|
339
339
|
accountId: z.ZodNullable<z.ZodString>;
|
|
@@ -1402,7 +1402,7 @@ declare const seoProfiles: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1402
1402
|
languageCode: string;
|
|
1403
1403
|
limit: number;
|
|
1404
1404
|
scope: {
|
|
1405
|
-
kind: "
|
|
1405
|
+
kind: "project" | "property" | "market" | "group";
|
|
1406
1406
|
key?: string | undefined;
|
|
1407
1407
|
expectedPlanRevision?: number | undefined;
|
|
1408
1408
|
};
|
|
@@ -1432,7 +1432,7 @@ declare const seoProfiles: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1432
1432
|
languageCode: string;
|
|
1433
1433
|
limit: number;
|
|
1434
1434
|
scope: {
|
|
1435
|
-
kind: "
|
|
1435
|
+
kind: "project" | "property" | "market" | "group";
|
|
1436
1436
|
key?: string | undefined;
|
|
1437
1437
|
expectedPlanRevision?: number | undefined;
|
|
1438
1438
|
};
|
|
@@ -1614,7 +1614,7 @@ declare const seoJobs: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1614
1614
|
languageCode: string;
|
|
1615
1615
|
limit: number;
|
|
1616
1616
|
scope: {
|
|
1617
|
-
kind: "
|
|
1617
|
+
kind: "project" | "property" | "market" | "group";
|
|
1618
1618
|
key?: string | undefined;
|
|
1619
1619
|
expectedPlanRevision?: number | undefined;
|
|
1620
1620
|
};
|
|
@@ -1644,7 +1644,7 @@ declare const seoJobs: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1644
1644
|
languageCode: string;
|
|
1645
1645
|
limit: number;
|
|
1646
1646
|
scope: {
|
|
1647
|
-
kind: "
|
|
1647
|
+
kind: "project" | "property" | "market" | "group";
|
|
1648
1648
|
key?: string | undefined;
|
|
1649
1649
|
expectedPlanRevision?: number | undefined;
|
|
1650
1650
|
};
|
|
@@ -1788,7 +1788,7 @@ declare const seoJobs: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1788
1788
|
tableName: "seo_jobs";
|
|
1789
1789
|
dataType: "string";
|
|
1790
1790
|
columnType: "SQLiteText";
|
|
1791
|
-
data: "queued" | "
|
|
1791
|
+
data: "queued" | "running" | "partial" | "failed" | "completed" | "cancelled" | "reconciliation-required";
|
|
1792
1792
|
driverParam: string;
|
|
1793
1793
|
notNull: true;
|
|
1794
1794
|
hasDefault: false;
|
|
@@ -1801,7 +1801,7 @@ declare const seoJobs: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1801
1801
|
generated: undefined;
|
|
1802
1802
|
}, {}, {
|
|
1803
1803
|
length: number | undefined;
|
|
1804
|
-
$type: "queued" | "
|
|
1804
|
+
$type: "queued" | "running" | "partial" | "failed" | "completed" | "cancelled" | "reconciliation-required";
|
|
1805
1805
|
}>;
|
|
1806
1806
|
cancelRequested: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1807
1807
|
name: "cancel_requested";
|
|
@@ -1965,7 +1965,7 @@ declare const seoTasks: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1965
1965
|
tableName: "seo_tasks";
|
|
1966
1966
|
dataType: "string";
|
|
1967
1967
|
columnType: "SQLiteText";
|
|
1968
|
-
data: "queued" | "
|
|
1968
|
+
data: "queued" | "running" | "partial" | "failed" | "completed" | "cancelled" | "reconciliation-required";
|
|
1969
1969
|
driverParam: string;
|
|
1970
1970
|
notNull: true;
|
|
1971
1971
|
hasDefault: false;
|
|
@@ -1978,7 +1978,7 @@ declare const seoTasks: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
1978
1978
|
generated: undefined;
|
|
1979
1979
|
}, {}, {
|
|
1980
1980
|
length: number | undefined;
|
|
1981
|
-
$type: "queued" | "
|
|
1981
|
+
$type: "queued" | "running" | "partial" | "failed" | "completed" | "cancelled" | "reconciliation-required";
|
|
1982
1982
|
}>;
|
|
1983
1983
|
leaseOwner: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
1984
1984
|
name: "lease_owner";
|
|
@@ -2627,7 +2627,7 @@ declare const projects: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2627
2627
|
tableName: "projects";
|
|
2628
2628
|
dataType: "string";
|
|
2629
2629
|
columnType: "SQLiteText";
|
|
2630
|
-
data: "
|
|
2630
|
+
data: "competitors" | "full";
|
|
2631
2631
|
driverParam: string;
|
|
2632
2632
|
notNull: false;
|
|
2633
2633
|
hasDefault: false;
|
|
@@ -2640,7 +2640,7 @@ declare const projects: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
2640
2640
|
generated: undefined;
|
|
2641
2641
|
}, {}, {
|
|
2642
2642
|
length: number | undefined;
|
|
2643
|
-
$type: "
|
|
2643
|
+
$type: "competitors" | "full";
|
|
2644
2644
|
}>;
|
|
2645
2645
|
country: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
2646
2646
|
name: "country";
|
|
@@ -5896,7 +5896,7 @@ declare const querySnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
5896
5896
|
tableName: "query_snapshots";
|
|
5897
5897
|
dataType: "string";
|
|
5898
5898
|
columnType: "SQLiteText";
|
|
5899
|
-
data: "unknown" | "
|
|
5899
|
+
data: "unknown" | "not-applicable" | "used" | "not-used";
|
|
5900
5900
|
driverParam: string;
|
|
5901
5901
|
notNull: false;
|
|
5902
5902
|
hasDefault: false;
|
|
@@ -5909,7 +5909,7 @@ declare const querySnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
5909
5909
|
generated: undefined;
|
|
5910
5910
|
}, {}, {
|
|
5911
5911
|
length: number | undefined;
|
|
5912
|
-
$type: "unknown" | "
|
|
5912
|
+
$type: "unknown" | "not-applicable" | "used" | "not-used";
|
|
5913
5913
|
}>;
|
|
5914
5914
|
retrievalContract: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
5915
5915
|
name: "retrieval_contract";
|
|
@@ -6257,8 +6257,8 @@ declare const querySnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
6257
6257
|
status?: string | null | undefined;
|
|
6258
6258
|
}[];
|
|
6259
6259
|
searchQueries: string[];
|
|
6260
|
-
retrievalStatus: "unknown" | "
|
|
6261
|
-
citationBasis: "
|
|
6260
|
+
retrievalStatus: "unknown" | "not-applicable" | "used" | "not-used";
|
|
6261
|
+
citationBasis: "none" | "mixed" | "answer-support" | "explicit-citation";
|
|
6262
6262
|
citationMeasurable: boolean;
|
|
6263
6263
|
directSourceUrls: boolean;
|
|
6264
6264
|
location: {
|
|
@@ -6362,8 +6362,8 @@ declare const querySnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
6362
6362
|
status?: string | null | undefined;
|
|
6363
6363
|
}[];
|
|
6364
6364
|
searchQueries: string[];
|
|
6365
|
-
retrievalStatus: "unknown" | "
|
|
6366
|
-
citationBasis: "
|
|
6365
|
+
retrievalStatus: "unknown" | "not-applicable" | "used" | "not-used";
|
|
6366
|
+
citationBasis: "none" | "mixed" | "answer-support" | "explicit-citation";
|
|
6367
6367
|
citationMeasurable: boolean;
|
|
6368
6368
|
directSourceUrls: boolean;
|
|
6369
6369
|
location: {
|
|
@@ -6777,7 +6777,7 @@ declare const providerBatches: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
6777
6777
|
tableName: "provider_batches";
|
|
6778
6778
|
dataType: "string";
|
|
6779
6779
|
columnType: "SQLiteText";
|
|
6780
|
-
data: "unknown" | "failed" | "
|
|
6780
|
+
data: "unknown" | "failed" | "submitted" | "submitting" | "ended" | "ingested" | "cancelled";
|
|
6781
6781
|
driverParam: string;
|
|
6782
6782
|
notNull: true;
|
|
6783
6783
|
hasDefault: false;
|
|
@@ -6790,7 +6790,7 @@ declare const providerBatches: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
6790
6790
|
generated: undefined;
|
|
6791
6791
|
}, {}, {
|
|
6792
6792
|
length: number | undefined;
|
|
6793
|
-
$type: "unknown" | "failed" | "
|
|
6793
|
+
$type: "unknown" | "failed" | "submitted" | "submitting" | "ended" | "ingested" | "cancelled";
|
|
6794
6794
|
}>;
|
|
6795
6795
|
requestCount: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
6796
6796
|
name: "request_count";
|
|
@@ -7236,7 +7236,7 @@ declare const providerBatchRequests: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
7236
7236
|
tableName: "provider_batch_requests";
|
|
7237
7237
|
dataType: "string";
|
|
7238
7238
|
columnType: "SQLiteText";
|
|
7239
|
-
data: "
|
|
7239
|
+
data: "duplicate" | "canceled" | "recorded" | "errored" | "expired" | "parse_failed";
|
|
7240
7240
|
driverParam: string;
|
|
7241
7241
|
notNull: false;
|
|
7242
7242
|
hasDefault: false;
|
|
@@ -7249,7 +7249,7 @@ declare const providerBatchRequests: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
7249
7249
|
generated: undefined;
|
|
7250
7250
|
}, {}, {
|
|
7251
7251
|
length: number | undefined;
|
|
7252
|
-
$type: "
|
|
7252
|
+
$type: "duplicate" | "canceled" | "recorded" | "errored" | "expired" | "parse_failed";
|
|
7253
7253
|
}>;
|
|
7254
7254
|
error: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
7255
7255
|
name: "error";
|
|
@@ -8837,7 +8837,7 @@ declare const oauthTokens: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
8837
8837
|
tableName: "oauth_tokens";
|
|
8838
8838
|
dataType: "string";
|
|
8839
8839
|
columnType: "SQLiteText";
|
|
8840
|
-
data: "
|
|
8840
|
+
data: "refresh" | "access";
|
|
8841
8841
|
driverParam: string;
|
|
8842
8842
|
notNull: true;
|
|
8843
8843
|
hasDefault: false;
|
|
@@ -8850,7 +8850,7 @@ declare const oauthTokens: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
8850
8850
|
generated: undefined;
|
|
8851
8851
|
}, {}, {
|
|
8852
8852
|
length: number | undefined;
|
|
8853
|
-
$type: "
|
|
8853
|
+
$type: "refresh" | "access";
|
|
8854
8854
|
}>;
|
|
8855
8855
|
clientId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
8856
8856
|
name: "client_id";
|
|
@@ -11873,7 +11873,7 @@ declare const siteAuditSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns
|
|
|
11873
11873
|
weight: number;
|
|
11874
11874
|
sharePct: number | null;
|
|
11875
11875
|
avgScore: number;
|
|
11876
|
-
status: "partial" | "
|
|
11876
|
+
status: "partial" | "fail" | "pass";
|
|
11877
11877
|
pagesPassing: number;
|
|
11878
11878
|
pagesPartial: number;
|
|
11879
11879
|
pagesFailing: number;
|
|
@@ -11895,7 +11895,7 @@ declare const siteAuditSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns
|
|
|
11895
11895
|
weight: number;
|
|
11896
11896
|
sharePct: number | null;
|
|
11897
11897
|
avgScore: number;
|
|
11898
|
-
status: "partial" | "
|
|
11898
|
+
status: "partial" | "fail" | "pass";
|
|
11899
11899
|
pagesPassing: number;
|
|
11900
11900
|
pagesPartial: number;
|
|
11901
11901
|
pagesFailing: number;
|
|
@@ -17281,7 +17281,7 @@ declare const gaLeadEventsDaily: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
17281
17281
|
tableName: "ga_lead_events_daily";
|
|
17282
17282
|
dataType: "string";
|
|
17283
17283
|
columnType: "SQLiteText";
|
|
17284
|
-
data: "
|
|
17284
|
+
data: "landing-page" | "channel";
|
|
17285
17285
|
driverParam: string;
|
|
17286
17286
|
notNull: true;
|
|
17287
17287
|
hasDefault: false;
|
|
@@ -17294,7 +17294,7 @@ declare const gaLeadEventsDaily: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
17294
17294
|
generated: undefined;
|
|
17295
17295
|
}, {}, {
|
|
17296
17296
|
length: number | undefined;
|
|
17297
|
-
$type: "
|
|
17297
|
+
$type: "landing-page" | "channel";
|
|
17298
17298
|
}>;
|
|
17299
17299
|
eventCount: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
17300
17300
|
name: "event_count";
|
|
@@ -17517,7 +17517,7 @@ declare const gaMeasurementSyncStates: drizzle_orm_sqlite_core.SQLiteTableWithCo
|
|
|
17517
17517
|
tableName: "ga_measurement_sync_state";
|
|
17518
17518
|
dataType: "string";
|
|
17519
17519
|
columnType: "SQLiteText";
|
|
17520
|
-
data: "
|
|
17520
|
+
data: "landing-page" | "channel";
|
|
17521
17521
|
driverParam: string;
|
|
17522
17522
|
notNull: false;
|
|
17523
17523
|
hasDefault: false;
|
|
@@ -17530,7 +17530,7 @@ declare const gaMeasurementSyncStates: drizzle_orm_sqlite_core.SQLiteTableWithCo
|
|
|
17530
17530
|
generated: undefined;
|
|
17531
17531
|
}, {}, {
|
|
17532
17532
|
length: number | undefined;
|
|
17533
|
-
$type: "
|
|
17533
|
+
$type: "landing-page" | "channel";
|
|
17534
17534
|
}>;
|
|
17535
17535
|
searchLandingStatus: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
17536
17536
|
name: "search_landing_status";
|
|
@@ -25055,7 +25055,7 @@ declare const discoverySessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
25055
25055
|
data: {
|
|
25056
25056
|
domain: string;
|
|
25057
25057
|
hits: number;
|
|
25058
|
-
competitorType: "unknown" | "direct-competitor" | "ota-aggregator" | "editorial-media"
|
|
25058
|
+
competitorType: "unknown" | "other" | "direct-competitor" | "ota-aggregator" | "editorial-media";
|
|
25059
25059
|
evaluator?: {
|
|
25060
25060
|
provider: string;
|
|
25061
25061
|
requestedModel: string;
|
|
@@ -25077,7 +25077,7 @@ declare const discoverySessions: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
25077
25077
|
$type: {
|
|
25078
25078
|
domain: string;
|
|
25079
25079
|
hits: number;
|
|
25080
|
-
competitorType: "unknown" | "direct-competitor" | "ota-aggregator" | "editorial-media"
|
|
25080
|
+
competitorType: "unknown" | "other" | "direct-competitor" | "ota-aggregator" | "editorial-media";
|
|
25081
25081
|
evaluator?: {
|
|
25082
25082
|
provider: string;
|
|
25083
25083
|
requestedModel: string;
|
|
@@ -25328,7 +25328,7 @@ declare const researchRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
25328
25328
|
dataType: "json";
|
|
25329
25329
|
columnType: "SQLiteTextJson";
|
|
25330
25330
|
data: {
|
|
25331
|
-
kind: "
|
|
25331
|
+
kind: "property" | "market";
|
|
25332
25332
|
key: string;
|
|
25333
25333
|
label: string;
|
|
25334
25334
|
planRevision: number;
|
|
@@ -25345,7 +25345,7 @@ declare const researchRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
25345
25345
|
generated: undefined;
|
|
25346
25346
|
}, {}, {
|
|
25347
25347
|
$type: {
|
|
25348
|
-
kind: "
|
|
25348
|
+
kind: "property" | "market";
|
|
25349
25349
|
key: string;
|
|
25350
25350
|
label: string;
|
|
25351
25351
|
planRevision: number;
|
|
@@ -25496,7 +25496,7 @@ declare const researchRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
25496
25496
|
dataType: "json";
|
|
25497
25497
|
columnType: "SQLiteTextJson";
|
|
25498
25498
|
data: {
|
|
25499
|
-
kind: "
|
|
25499
|
+
kind: "user" | "api-key";
|
|
25500
25500
|
id: string;
|
|
25501
25501
|
name: string;
|
|
25502
25502
|
role: "admin" | "viewer" | null;
|
|
@@ -25514,7 +25514,7 @@ declare const researchRuns: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
25514
25514
|
generated: undefined;
|
|
25515
25515
|
}, {}, {
|
|
25516
25516
|
$type: {
|
|
25517
|
-
kind: "
|
|
25517
|
+
kind: "user" | "api-key";
|
|
25518
25518
|
id: string;
|
|
25519
25519
|
name: string;
|
|
25520
25520
|
role: "admin" | "viewer" | null;
|
|
@@ -26051,8 +26051,8 @@ declare const researchRunQueries: drizzle_orm_sqlite_core.SQLiteTableWithColumns
|
|
|
26051
26051
|
status?: string | null | undefined;
|
|
26052
26052
|
}[];
|
|
26053
26053
|
searchQueries: string[];
|
|
26054
|
-
retrievalStatus: "unknown" | "
|
|
26055
|
-
citationBasis: "
|
|
26054
|
+
retrievalStatus: "unknown" | "not-applicable" | "used" | "not-used";
|
|
26055
|
+
citationBasis: "none" | "mixed" | "answer-support" | "explicit-citation";
|
|
26056
26056
|
citationMeasurable: boolean;
|
|
26057
26057
|
directSourceUrls: boolean;
|
|
26058
26058
|
location: {
|
|
@@ -26156,8 +26156,8 @@ declare const researchRunQueries: drizzle_orm_sqlite_core.SQLiteTableWithColumns
|
|
|
26156
26156
|
status?: string | null | undefined;
|
|
26157
26157
|
}[];
|
|
26158
26158
|
searchQueries: string[];
|
|
26159
|
-
retrievalStatus: "unknown" | "
|
|
26160
|
-
citationBasis: "
|
|
26159
|
+
retrievalStatus: "unknown" | "not-applicable" | "used" | "not-used";
|
|
26160
|
+
citationBasis: "none" | "mixed" | "answer-support" | "explicit-citation";
|
|
26161
26161
|
citationMeasurable: boolean;
|
|
26162
26162
|
directSourceUrls: boolean;
|
|
26163
26163
|
location: {
|
|
@@ -26538,7 +26538,7 @@ declare const domainClassifications: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
26538
26538
|
tableName: "domain_classifications";
|
|
26539
26539
|
dataType: "string";
|
|
26540
26540
|
columnType: "SQLiteText";
|
|
26541
|
-
data: "unknown" | "direct-competitor" | "ota-aggregator" | "editorial-media"
|
|
26541
|
+
data: "unknown" | "other" | "direct-competitor" | "ota-aggregator" | "editorial-media";
|
|
26542
26542
|
driverParam: string;
|
|
26543
26543
|
notNull: true;
|
|
26544
26544
|
hasDefault: false;
|
|
@@ -26551,7 +26551,7 @@ declare const domainClassifications: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
26551
26551
|
generated: undefined;
|
|
26552
26552
|
}, {}, {
|
|
26553
26553
|
length: number | undefined;
|
|
26554
|
-
$type: "unknown" | "direct-competitor" | "ota-aggregator" | "editorial-media"
|
|
26554
|
+
$type: "unknown" | "other" | "direct-competitor" | "ota-aggregator" | "editorial-media";
|
|
26555
26555
|
}>;
|
|
26556
26556
|
hits: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
26557
26557
|
name: "hits";
|
|
@@ -29140,7 +29140,7 @@ declare const gbpReviews: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
29140
29140
|
tableName: "gbp_reviews";
|
|
29141
29141
|
dataType: "string";
|
|
29142
29142
|
columnType: "SQLiteText";
|
|
29143
|
-
data: "
|
|
29143
|
+
data: "none" | "baseline" | "stale" | "pending" | "sent" | "skipped" | "suppressed";
|
|
29144
29144
|
driverParam: string;
|
|
29145
29145
|
notNull: true;
|
|
29146
29146
|
hasDefault: true;
|
|
@@ -29153,7 +29153,7 @@ declare const gbpReviews: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
29153
29153
|
generated: undefined;
|
|
29154
29154
|
}, {}, {
|
|
29155
29155
|
length: number | undefined;
|
|
29156
|
-
$type: "
|
|
29156
|
+
$type: "none" | "baseline" | "stale" | "pending" | "sent" | "skipped" | "suppressed";
|
|
29157
29157
|
}>;
|
|
29158
29158
|
alertStateAt: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
29159
29159
|
name: "alert_state_at";
|
|
@@ -29450,7 +29450,7 @@ declare const gbpReviewRatings: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
29450
29450
|
tableName: "gbp_review_ratings";
|
|
29451
29451
|
dataType: "string";
|
|
29452
29452
|
columnType: "SQLiteText";
|
|
29453
|
-
data: "
|
|
29453
|
+
data: "none" | "baseline" | "stale" | "pending" | "sent" | "skipped" | "suppressed";
|
|
29454
29454
|
driverParam: string;
|
|
29455
29455
|
notNull: true;
|
|
29456
29456
|
hasDefault: true;
|
|
@@ -29463,7 +29463,7 @@ declare const gbpReviewRatings: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
29463
29463
|
generated: undefined;
|
|
29464
29464
|
}, {}, {
|
|
29465
29465
|
length: number | undefined;
|
|
29466
|
-
$type: "
|
|
29466
|
+
$type: "none" | "baseline" | "stale" | "pending" | "sent" | "skipped" | "suppressed";
|
|
29467
29467
|
}>;
|
|
29468
29468
|
alertStateAt: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
29469
29469
|
name: "alert_state_at";
|
|
@@ -30709,7 +30709,7 @@ declare const adsOperationSteps: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
30709
30709
|
tableName: "ads_operation_steps";
|
|
30710
30710
|
dataType: "string";
|
|
30711
30711
|
columnType: "SQLiteText";
|
|
30712
|
-
data: "unknown" | "failed" | "
|
|
30712
|
+
data: "unknown" | "failed" | "active" | "pending" | "executing" | "rollback_executing" | "rolled_back" | "rollback_failed";
|
|
30713
30713
|
driverParam: string;
|
|
30714
30714
|
notNull: true;
|
|
30715
30715
|
hasDefault: false;
|
|
@@ -30722,7 +30722,7 @@ declare const adsOperationSteps: drizzle_orm_sqlite_core.SQLiteTableWithColumns<
|
|
|
30722
30722
|
generated: undefined;
|
|
30723
30723
|
}, {}, {
|
|
30724
30724
|
length: number | undefined;
|
|
30725
|
-
$type: "unknown" | "failed" | "
|
|
30725
|
+
$type: "unknown" | "failed" | "active" | "pending" | "executing" | "rollback_executing" | "rolled_back" | "rollback_failed";
|
|
30726
30726
|
}>;
|
|
30727
30727
|
providerUpdatedAt: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
30728
30728
|
name: "provider_updated_at";
|
|
@@ -32029,7 +32029,7 @@ declare const googleAdsConnections: drizzle_orm_sqlite_core.SQLiteTableWithColum
|
|
|
32029
32029
|
tableName: "google_ads_connections";
|
|
32030
32030
|
dataType: "string";
|
|
32031
32031
|
columnType: "SQLiteText";
|
|
32032
|
-
data: "unknown" | "
|
|
32032
|
+
data: "unknown" | "enabled" | "suspended" | "closed" | "canceled" | "unspecified";
|
|
32033
32033
|
driverParam: string;
|
|
32034
32034
|
notNull: false;
|
|
32035
32035
|
hasDefault: false;
|
|
@@ -32042,7 +32042,7 @@ declare const googleAdsConnections: drizzle_orm_sqlite_core.SQLiteTableWithColum
|
|
|
32042
32042
|
generated: undefined;
|
|
32043
32043
|
}, {}, {
|
|
32044
32044
|
length: number | undefined;
|
|
32045
|
-
$type: "unknown" | "
|
|
32045
|
+
$type: "unknown" | "enabled" | "suspended" | "closed" | "canceled" | "unspecified";
|
|
32046
32046
|
}>;
|
|
32047
32047
|
scopes: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
32048
32048
|
name: "scopes";
|
|
@@ -32989,7 +32989,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
32989
32989
|
hidden: boolean;
|
|
32990
32990
|
testAccount: boolean;
|
|
32991
32991
|
level: number;
|
|
32992
|
-
status: "unknown" | "
|
|
32992
|
+
status: "unknown" | "enabled" | "suspended" | "closed" | "canceled" | "unspecified";
|
|
32993
32993
|
}[];
|
|
32994
32994
|
totalAccessible: number;
|
|
32995
32995
|
truncated: boolean;
|
|
@@ -33009,7 +33009,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33009
33009
|
id: string;
|
|
33010
33010
|
resourceName: string;
|
|
33011
33011
|
name: string;
|
|
33012
|
-
status: "unknown" | "enabled" | "
|
|
33012
|
+
status: "unknown" | "enabled" | "removed" | "paused";
|
|
33013
33013
|
advertisingChannelType: string | null;
|
|
33014
33014
|
biddingStrategyType: string | null;
|
|
33015
33015
|
}[];
|
|
@@ -33017,7 +33017,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33017
33017
|
id: string;
|
|
33018
33018
|
resourceName: string;
|
|
33019
33019
|
name: string;
|
|
33020
|
-
status: "unknown" | "enabled" | "
|
|
33020
|
+
status: "unknown" | "enabled" | "removed" | "hidden";
|
|
33021
33021
|
category: string;
|
|
33022
33022
|
origin: string;
|
|
33023
33023
|
primaryForGoal: boolean;
|
|
@@ -33041,7 +33041,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33041
33041
|
}[];
|
|
33042
33042
|
campaignGoalConfigurations: {
|
|
33043
33043
|
campaignId: string;
|
|
33044
|
-
goalConfigLevel: "
|
|
33044
|
+
goalConfigLevel: "customer" | "campaign";
|
|
33045
33045
|
customGoalId: string | null;
|
|
33046
33046
|
}[];
|
|
33047
33047
|
campaignConversionGoalsComplete?: boolean | undefined;
|
|
@@ -33092,7 +33092,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33092
33092
|
hidden: boolean;
|
|
33093
33093
|
testAccount: boolean;
|
|
33094
33094
|
level: number;
|
|
33095
|
-
status: "unknown" | "
|
|
33095
|
+
status: "unknown" | "enabled" | "suspended" | "closed" | "canceled" | "unspecified";
|
|
33096
33096
|
}[];
|
|
33097
33097
|
totalAccessible: number;
|
|
33098
33098
|
truncated: boolean;
|
|
@@ -33112,7 +33112,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33112
33112
|
id: string;
|
|
33113
33113
|
resourceName: string;
|
|
33114
33114
|
name: string;
|
|
33115
|
-
status: "unknown" | "enabled" | "
|
|
33115
|
+
status: "unknown" | "enabled" | "removed" | "paused";
|
|
33116
33116
|
advertisingChannelType: string | null;
|
|
33117
33117
|
biddingStrategyType: string | null;
|
|
33118
33118
|
}[];
|
|
@@ -33120,7 +33120,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33120
33120
|
id: string;
|
|
33121
33121
|
resourceName: string;
|
|
33122
33122
|
name: string;
|
|
33123
|
-
status: "unknown" | "enabled" | "
|
|
33123
|
+
status: "unknown" | "enabled" | "removed" | "hidden";
|
|
33124
33124
|
category: string;
|
|
33125
33125
|
origin: string;
|
|
33126
33126
|
primaryForGoal: boolean;
|
|
@@ -33144,7 +33144,7 @@ declare const googleAdsRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColu
|
|
|
33144
33144
|
}[];
|
|
33145
33145
|
campaignGoalConfigurations: {
|
|
33146
33146
|
campaignId: string;
|
|
33147
|
-
goalConfigLevel: "
|
|
33147
|
+
goalConfigLevel: "customer" | "campaign";
|
|
33148
33148
|
customGoalId: string | null;
|
|
33149
33149
|
}[];
|
|
33150
33150
|
campaignConversionGoalsComplete?: boolean | undefined;
|
|
@@ -33301,7 +33301,7 @@ declare const gtmRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
33301
33301
|
tableName: "gtm_raw_snapshots";
|
|
33302
33302
|
dataType: "string";
|
|
33303
33303
|
columnType: "SQLiteText";
|
|
33304
|
-
data: "
|
|
33304
|
+
data: "live" | "accounts" | "container" | "draft";
|
|
33305
33305
|
driverParam: string;
|
|
33306
33306
|
notNull: true;
|
|
33307
33307
|
hasDefault: false;
|
|
@@ -33314,7 +33314,7 @@ declare const gtmRawSnapshots: drizzle_orm_sqlite_core.SQLiteTableWithColumns<{
|
|
|
33314
33314
|
generated: undefined;
|
|
33315
33315
|
}, {}, {
|
|
33316
33316
|
length: number | undefined;
|
|
33317
|
-
$type: "
|
|
33317
|
+
$type: "live" | "accounts" | "container" | "draft";
|
|
33318
33318
|
}>;
|
|
33319
33319
|
accountId: drizzle_orm_sqlite_core.SQLiteColumn<{
|
|
33320
33320
|
name: "account_id";
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "7.62.
|
|
3
|
+
"version": "7.62.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
|
|
6
6
|
"keywords": [
|