@ainyc/canonry 4.42.0 → 4.44.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/assets/assets/index-jvmhx0du.css +1 -0
- package/assets/assets/{index-NUBexmUO.js → index-kRilKhIW.js} +57 -57
- package/assets/index.html +2 -2
- package/dist/{chunk-BPJATXCC.js → chunk-MITJYCHG.js} +54 -0
- package/dist/{chunk-D37LKESQ.js → chunk-U73SXACQ.js} +33 -3
- package/dist/cli.js +32 -2
- package/dist/index.js +2 -2
- package/dist/{intelligence-service-NPBBAN4Y.js → intelligence-service-HWWNLBZM.js} +1 -1
- package/package.json +5 -5
- package/assets/assets/index-DdOq6OIk.css +0 -1
package/assets/index.html
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
16
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-kRilKhIW.js"></script>
|
|
16
|
+
<link rel="stylesheet" crossorigin href="./assets/index-jvmhx0du.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
19
19
|
<div id="root"></div>
|
|
@@ -3740,6 +3740,59 @@ function describe(parts) {
|
|
|
3740
3740
|
return `${score}% of brand mentions are you. Top competitor: ${top.domain} (${top.mentionSnapshots} mentions).`;
|
|
3741
3741
|
}
|
|
3742
3742
|
|
|
3743
|
+
// ../intelligence/src/suggested-queries.ts
|
|
3744
|
+
var DEFAULT_MIN_IMPRESSIONS = 10;
|
|
3745
|
+
var DEFAULT_LIMIT = 10;
|
|
3746
|
+
function buildSuggestedQueries(gscRows, options) {
|
|
3747
|
+
const minImpressions = options.minImpressions ?? DEFAULT_MIN_IMPRESSIONS;
|
|
3748
|
+
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
3749
|
+
const trackedSet = new Set(options.trackedQueries.map(normalizeQuery));
|
|
3750
|
+
let skippedAlreadyTracked = 0;
|
|
3751
|
+
const candidates = [];
|
|
3752
|
+
for (const row of gscRows) {
|
|
3753
|
+
if (row.impressions < minImpressions) continue;
|
|
3754
|
+
const normalized = normalizeQuery(row.query);
|
|
3755
|
+
if (normalized.length === 0) continue;
|
|
3756
|
+
if (trackedSet.has(normalized)) {
|
|
3757
|
+
skippedAlreadyTracked++;
|
|
3758
|
+
continue;
|
|
3759
|
+
}
|
|
3760
|
+
candidates.push({
|
|
3761
|
+
query: row.query,
|
|
3762
|
+
impressions: row.impressions,
|
|
3763
|
+
clicks: row.clicks,
|
|
3764
|
+
avgPosition: row.avgPosition,
|
|
3765
|
+
reason: buildReason(row)
|
|
3766
|
+
});
|
|
3767
|
+
}
|
|
3768
|
+
candidates.sort((a, b) => b.impressions - a.impressions);
|
|
3769
|
+
const rows = candidates.slice(0, limit);
|
|
3770
|
+
return {
|
|
3771
|
+
rows,
|
|
3772
|
+
totalCandidates: candidates.length,
|
|
3773
|
+
skippedAlreadyTracked
|
|
3774
|
+
};
|
|
3775
|
+
}
|
|
3776
|
+
function normalizeQuery(value) {
|
|
3777
|
+
return value.trim().toLowerCase();
|
|
3778
|
+
}
|
|
3779
|
+
function buildReason(row) {
|
|
3780
|
+
const impressionsLabel = formatImpressions2(row.impressions);
|
|
3781
|
+
if (row.avgPosition <= 10) {
|
|
3782
|
+
return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)} on Google`;
|
|
3783
|
+
}
|
|
3784
|
+
if (row.avgPosition <= 20) {
|
|
3785
|
+
return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)} \u2014 close to top 10`;
|
|
3786
|
+
}
|
|
3787
|
+
return `${impressionsLabel} impressions \xB7 ranks #${Math.round(row.avgPosition)}`;
|
|
3788
|
+
}
|
|
3789
|
+
function formatImpressions2(value) {
|
|
3790
|
+
if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
|
|
3791
|
+
if (value >= 1e4) return `${Math.round(value / 1e3)}K`;
|
|
3792
|
+
if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
|
|
3793
|
+
return value.toString();
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3743
3796
|
// src/intelligence-service.ts
|
|
3744
3797
|
import crypto from "crypto";
|
|
3745
3798
|
|
|
@@ -4269,6 +4322,7 @@ export {
|
|
|
4269
4322
|
buildProviderTrends,
|
|
4270
4323
|
providerKey,
|
|
4271
4324
|
buildMentionShare,
|
|
4325
|
+
buildSuggestedQueries,
|
|
4272
4326
|
createLogger,
|
|
4273
4327
|
IntelligenceService
|
|
4274
4328
|
};
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
buildProviderScores,
|
|
39
39
|
buildProviderTrends,
|
|
40
40
|
buildRunHistory,
|
|
41
|
+
buildSuggestedQueries,
|
|
41
42
|
buildVisibilityScore,
|
|
42
43
|
categorizeQueryByIntent,
|
|
43
44
|
ccReleaseSyncs,
|
|
@@ -78,7 +79,7 @@ import {
|
|
|
78
79
|
schedules,
|
|
79
80
|
trafficSources,
|
|
80
81
|
usageCounters
|
|
81
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-MITJYCHG.js";
|
|
82
83
|
import {
|
|
83
84
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
84
85
|
AGENT_PROVIDER_IDS,
|
|
@@ -4330,7 +4331,7 @@ function renderCompetitorLandscape(report) {
|
|
|
4330
4331
|
</tr>`;
|
|
4331
4332
|
}).join("");
|
|
4332
4333
|
const table = competitors2.length > 0 ? `<table class="report-table">
|
|
4333
|
-
<thead><tr><th>Domain</th><th>Pressure</th><th>Citations</th><th class="numeric">Mentions</th><th class="numeric">
|
|
4334
|
+
<thead><tr><th>Domain</th><th>Pressure</th><th>Citations</th><th class="numeric">Mentions</th><th class="numeric" title="Citation share \u2014 % of cited-source slots that went to this competitor across tracked queries. Distinct from Mention Share.">Citation share</th><th>Cited queries</th></tr></thead>
|
|
4334
4335
|
<tbody>${rows}</tbody>
|
|
4335
4336
|
</table>` : renderEmpty("No competitors configured.");
|
|
4336
4337
|
const citationBars = renderCompetitorBars(report.competitorLandscape, report.meta.project.canonicalDomain);
|
|
@@ -7287,6 +7288,11 @@ async function compositeRoutes(app) {
|
|
|
7287
7288
|
const attentionItems = buildAttentionItems(insightRows, allRuns);
|
|
7288
7289
|
const sparklineRuns = visibilityRuns.slice(0, DEFAULT_RUN_HISTORY_LIMIT).map((r) => ({ id: r.id, createdAt: r.createdAt, status: r.status }));
|
|
7289
7290
|
const runHistory = buildRunHistory(sparklineRuns, snapshotsByRun);
|
|
7291
|
+
const suggestedQueries = buildSuggestedQueriesFromGsc(
|
|
7292
|
+
app,
|
|
7293
|
+
project.id,
|
|
7294
|
+
projectQueries.map((q) => q.query)
|
|
7295
|
+
);
|
|
7290
7296
|
const result = {
|
|
7291
7297
|
project: formatProject2(project),
|
|
7292
7298
|
latestRun,
|
|
@@ -7301,6 +7307,7 @@ async function compositeRoutes(app) {
|
|
|
7301
7307
|
providerScores,
|
|
7302
7308
|
attentionItems,
|
|
7303
7309
|
runHistory,
|
|
7310
|
+
suggestedQueries,
|
|
7304
7311
|
dateRangeLabel: "All time",
|
|
7305
7312
|
contextLabel: `${project.country} / ${project.language.toUpperCase()}`
|
|
7306
7313
|
};
|
|
@@ -7502,6 +7509,29 @@ function summarizeTransitionsFromSnapshots(latest, previous, since) {
|
|
|
7502
7509
|
}
|
|
7503
7510
|
return { since, gained, lost, emerging };
|
|
7504
7511
|
}
|
|
7512
|
+
function buildSuggestedQueriesFromGsc(app, projectId, trackedQueries) {
|
|
7513
|
+
const cutoff = new Date(Date.now() - 28 * 24 * 60 * 60 * 1e3).toISOString().slice(0, 10);
|
|
7514
|
+
const rows = app.db.select({
|
|
7515
|
+
query: gscSearchData.query,
|
|
7516
|
+
impressions: sql6`COALESCE(SUM(${gscSearchData.impressions}), 0)`,
|
|
7517
|
+
clicks: sql6`COALESCE(SUM(${gscSearchData.clicks}), 0)`,
|
|
7518
|
+
// Weighted average: SUM(position * impressions) / SUM(impressions).
|
|
7519
|
+
// NULLIF guards the degenerate impressions=0 case (SQLite returns NULL,
|
|
7520
|
+
// which the JS coerces to 0 — caught by the impression floor anyway).
|
|
7521
|
+
avgPosition: sql6`COALESCE(SUM(${gscSearchData.position} * ${gscSearchData.impressions}) * 1.0 / NULLIF(SUM(${gscSearchData.impressions}), 0), 0)`
|
|
7522
|
+
}).from(gscSearchData).where(and7(
|
|
7523
|
+
eq15(gscSearchData.projectId, projectId),
|
|
7524
|
+
sql6`${gscSearchData.date} >= ${cutoff}`,
|
|
7525
|
+
sql6`${gscSearchData.impressions} > 0`
|
|
7526
|
+
)).groupBy(gscSearchData.query).orderBy(sql6`SUM(${gscSearchData.impressions}) DESC`).limit(100).all();
|
|
7527
|
+
const gscRows = rows.map((r) => ({
|
|
7528
|
+
query: r.query,
|
|
7529
|
+
impressions: Number(r.impressions),
|
|
7530
|
+
clicks: Number(r.clicks),
|
|
7531
|
+
avgPosition: Number(r.avgPosition)
|
|
7532
|
+
}));
|
|
7533
|
+
return buildSuggestedQueries(gscRows, { trackedQueries });
|
|
7534
|
+
}
|
|
7505
7535
|
function buildIndexCoverageScore(app, projectId) {
|
|
7506
7536
|
const tooltip = "Percentage of inspected URLs currently indexed. Google Search Console is preferred when available, otherwise Bing Webmaster Tools is used.";
|
|
7507
7537
|
const empty = {
|
|
@@ -26279,7 +26309,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
26279
26309
|
return result;
|
|
26280
26310
|
}
|
|
26281
26311
|
async function backfillInsightsCommand(project, opts) {
|
|
26282
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
26312
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-HWWNLBZM.js");
|
|
26283
26313
|
const config = loadConfig();
|
|
26284
26314
|
const db = createClient(config.database);
|
|
26285
26315
|
migrate(db);
|
package/dist/cli.js
CHANGED
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
setTelemetrySource,
|
|
22
22
|
showFirstRunNotice,
|
|
23
23
|
trackEvent
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-U73SXACQ.js";
|
|
25
25
|
import {
|
|
26
26
|
CliError,
|
|
27
27
|
EXIT_SYSTEM_ERROR,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
migrate,
|
|
45
45
|
projects,
|
|
46
46
|
queries
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-MITJYCHG.js";
|
|
48
48
|
import {
|
|
49
49
|
CcReleaseSyncStatuses,
|
|
50
50
|
CheckScopes,
|
|
@@ -8081,6 +8081,7 @@ function renderHuman(overview) {
|
|
|
8081
8081
|
providerScores,
|
|
8082
8082
|
attentionItems,
|
|
8083
8083
|
runHistory,
|
|
8084
|
+
suggestedQueries,
|
|
8084
8085
|
dateRangeLabel,
|
|
8085
8086
|
contextLabel
|
|
8086
8087
|
} = overview;
|
|
@@ -8096,7 +8097,11 @@ function renderHuman(overview) {
|
|
|
8096
8097
|
console.log("\n No runs yet.");
|
|
8097
8098
|
}
|
|
8098
8099
|
console.log("\nScores:");
|
|
8100
|
+
printScore("Mention ", scores.mention);
|
|
8099
8101
|
printScore("Visibility ", scores.visibility);
|
|
8102
|
+
printScore("Mention share ", scores.mentionShare);
|
|
8103
|
+
printMentionShareBreakdown(scores.mentionShare);
|
|
8104
|
+
printScore("Mention gaps ", scores.mentionGaps);
|
|
8100
8105
|
printScore("Gap queries ", scores.gapQueries);
|
|
8101
8106
|
printScore("Index coverage ", scores.indexCoverage);
|
|
8102
8107
|
printScore("Competitor press.", scores.competitorPressure);
|
|
@@ -8156,12 +8161,37 @@ function renderHuman(overview) {
|
|
|
8156
8161
|
console.log(` ${point.createdAt.slice(0, 10)} ${String(point.citationRate).padStart(3)}% ${bar}`);
|
|
8157
8162
|
}
|
|
8158
8163
|
}
|
|
8164
|
+
if (suggestedQueries.rows.length > 0) {
|
|
8165
|
+
const moreLabel = suggestedQueries.totalCandidates > suggestedQueries.rows.length ? ` (showing ${suggestedQueries.rows.length} of ${suggestedQueries.totalCandidates})` : "";
|
|
8166
|
+
console.log(`
|
|
8167
|
+
Suggested queries to track${moreLabel}:`);
|
|
8168
|
+
for (const s of suggestedQueries.rows) {
|
|
8169
|
+
console.log(` + ${s.query}`);
|
|
8170
|
+
console.log(` ${s.reason}`);
|
|
8171
|
+
}
|
|
8172
|
+
console.log(` (add via: canonry query add ${meta.name} "<query>")`);
|
|
8173
|
+
}
|
|
8159
8174
|
}
|
|
8160
8175
|
function printScore(prefix, score) {
|
|
8161
8176
|
const tone = `[${score.tone}]`.padEnd(11);
|
|
8162
8177
|
const value = score.value.padEnd(8);
|
|
8163
8178
|
console.log(` ${prefix} ${tone} ${value} ${score.delta}`);
|
|
8164
8179
|
}
|
|
8180
|
+
function printMentionShareBreakdown(mentionShare) {
|
|
8181
|
+
const { breakdown } = mentionShare;
|
|
8182
|
+
if (breakdown.perCompetitor.length === 0) return;
|
|
8183
|
+
const total = breakdown.projectMentionSnapshots + breakdown.competitorMentionSnapshots;
|
|
8184
|
+
if (total === 0) return;
|
|
8185
|
+
const youPct = (breakdown.projectMentionSnapshots / total * 100).toFixed(1);
|
|
8186
|
+
console.log(` you${" ".repeat(28)} ${breakdown.projectMentionSnapshots} mentions (${youPct}% of combined)`);
|
|
8187
|
+
for (const row of breakdown.perCompetitor.slice(0, 3)) {
|
|
8188
|
+
const pct2 = (row.mentionSnapshots / total * 100).toFixed(1);
|
|
8189
|
+
console.log(` ${row.domain.padEnd(30)} ${row.mentionSnapshots} mentions (${pct2}% of combined)`);
|
|
8190
|
+
}
|
|
8191
|
+
if (breakdown.perCompetitor.length > 3) {
|
|
8192
|
+
console.log(` + ${breakdown.perCompetitor.length - 3} more competitor${breakdown.perCompetitor.length - 3 === 1 ? "" : "s"} (--format json for full breakdown)`);
|
|
8193
|
+
}
|
|
8194
|
+
}
|
|
8165
8195
|
function pct(value) {
|
|
8166
8196
|
return `${(value * 100).toFixed(1)}%`;
|
|
8167
8197
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-U73SXACQ.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
6
|
} from "./chunk-JZ2VJW4U.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-MITJYCHG.js";
|
|
8
8
|
import "./chunk-Q7XFJO2V.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.44.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Agent-first open-source AEO operating platform - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -60,17 +60,17 @@
|
|
|
60
60
|
"@types/node-cron": "^3.0.11",
|
|
61
61
|
"tsup": "^8.5.1",
|
|
62
62
|
"tsx": "^4.19.0",
|
|
63
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
64
63
|
"@ainyc/canonry-config": "0.0.0",
|
|
64
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
65
65
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
66
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
67
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
68
66
|
"@ainyc/canonry-db": "0.0.0",
|
|
69
67
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
70
70
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
72
71
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
73
72
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
73
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
74
74
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
75
75
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
76
76
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|