@canonry/canonry 7.16.0 → 7.17.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/canonry/references/canonry-cli.md +22 -6
- package/assets/assets/{AuditHistoryPanel-Cl9tUvSZ.js → AuditHistoryPanel-CzjskfMX.js} +1 -1
- package/assets/assets/{BacklinksPage-CTeTJ9dh.js → BacklinksPage-ToENGBdp.js} +1 -1
- package/assets/assets/{HistoryPage-DpOoXr2P.js → HistoryPage-BZgVoYGm.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-DxXsgM25.js → MeasurementPropertyPage-EBI5sn-D.js} +1 -1
- package/assets/assets/ProjectPage-lGGjM_qj.js +8 -0
- package/assets/assets/{RunsPage-CfDi7I1z.js → RunsPage-CuHi8241.js} +1 -1
- package/assets/assets/{SettingsPage-BHDb1apK.js → SettingsPage-D0fgAoVu.js} +1 -1
- package/assets/assets/{SiteHealthSection-DQZyy4P_.js → SiteHealthSection-DhLxldgs.js} +3 -3
- package/assets/assets/{TrafficPage-DX_vN2RL.js → TrafficPage-DD65RqeR.js} +2 -2
- package/assets/assets/{TrafficSourceDetailPage-Cg92zrtZ.js → TrafficSourceDetailPage-CFVCj13J.js} +1 -1
- package/assets/assets/{extract-error-message-BKxVCbov.js → extract-error-message-D118msoE.js} +1 -1
- package/assets/assets/{index-DoQJETc6.js → index-DxFd1t4G.js} +26 -26
- package/assets/assets/{react-sigma_core.esm.min-BhqZcSgh.js → react-sigma_core.esm.min-DdlHLMEz.js} +1 -1
- package/assets/assets/{v2-overview-adapter-DZ5YsE_G.js → v2-overview-adapter-CoCb2aB0.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-2S7U2YHI.js → chunk-C6GWKYGE.js} +2 -2
- package/dist/{chunk-KDWTNI4Z.js → chunk-FK7AWV57.js} +23 -1
- package/dist/{chunk-6LS2R477.js → chunk-MHB23E3N.js} +103 -2
- package/dist/{chunk-O6XPXEN6.js → chunk-OPJCFDNR.js} +3 -3
- package/dist/{chunk-VWSUFTW5.js → chunk-ORA5R7QM.js} +6 -6
- package/dist/{chunk-3ZGBSHZ2.js → chunk-PLS4EM2Y.js} +30 -3
- package/dist/{chunk-SPZRSKCF.js → chunk-ZQ7C6IFA.js} +1381 -797
- package/dist/cli.js +124 -12
- package/dist/{demo-server-6OE3H2KL.js → demo-server-WQDHQG6P.js} +68 -15
- package/dist/index.js +6 -6
- package/dist/{intelligence-service-USSTKAKC.js → intelligence-service-JWZRZ6JZ.js} +2 -2
- package/dist/mcp.js +4 -4
- package/package.json +12 -12
- package/assets/assets/ProjectPage-By9arjLJ.js +0 -8
package/dist/cli.js
CHANGED
|
@@ -33,11 +33,11 @@ import {
|
|
|
33
33
|
trackCliCommandFinished,
|
|
34
34
|
trackEvent,
|
|
35
35
|
waitForServerRuntimeStartup
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-ORA5R7QM.js";
|
|
37
37
|
import {
|
|
38
38
|
autoSyncSkills,
|
|
39
39
|
formatAutoSyncNotice
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-OPJCFDNR.js";
|
|
41
41
|
import {
|
|
42
42
|
configExists,
|
|
43
43
|
createApiClient,
|
|
@@ -54,13 +54,13 @@ import {
|
|
|
54
54
|
saveConfig,
|
|
55
55
|
saveConfigPatch,
|
|
56
56
|
shouldPrintServeSkillsNudge
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-PLS4EM2Y.js";
|
|
58
58
|
import {
|
|
59
59
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
60
60
|
trustedProxiesProblem,
|
|
61
61
|
trustedProxyProblem
|
|
62
62
|
} from "./chunk-RB2F4D3Z.js";
|
|
63
|
-
import "./chunk-
|
|
63
|
+
import "./chunk-C6GWKYGE.js";
|
|
64
64
|
import {
|
|
65
65
|
CliError,
|
|
66
66
|
EXIT_SYSTEM_ERROR,
|
|
@@ -72,7 +72,7 @@ import {
|
|
|
72
72
|
runMeasurementDraftAction,
|
|
73
73
|
systemError,
|
|
74
74
|
usageError
|
|
75
|
-
} from "./chunk-
|
|
75
|
+
} from "./chunk-FK7AWV57.js";
|
|
76
76
|
import {
|
|
77
77
|
CLOUDFLARE_WORKER_BINDINGS,
|
|
78
78
|
CLOUDFLARE_WORKER_GENERATED_MARKER,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
rawEventSamples,
|
|
105
105
|
readMarketCompetitorNames,
|
|
106
106
|
runs
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-ZQ7C6IFA.js";
|
|
108
108
|
import {
|
|
109
109
|
AdsDeliverySnapshotStatuses,
|
|
110
110
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -119,6 +119,7 @@ import {
|
|
|
119
119
|
CitationStates,
|
|
120
120
|
DiscoveryPromoteCompetitorSkipReasons,
|
|
121
121
|
FEEDBACK_KINDS,
|
|
122
|
+
GA_SEARCH_LANDING_WINDOW_DAYS,
|
|
122
123
|
GaMoverChangeBases,
|
|
123
124
|
MeasurementEvidenceShapes,
|
|
124
125
|
OUTSTANDING_PROVIDER_BATCH_STATUSES,
|
|
@@ -181,6 +182,8 @@ import {
|
|
|
181
182
|
formatRunErrorOneLine,
|
|
182
183
|
formatSignedPointDelta,
|
|
183
184
|
formatSiteAuditPageBudget,
|
|
185
|
+
gaSearchLandingHasSearchData,
|
|
186
|
+
gaSearchLandingPageLabel,
|
|
184
187
|
gbpNegativeReviewMaxStarsSchema,
|
|
185
188
|
googleAdsMetricsWindowSchema,
|
|
186
189
|
isRetiredAgentProviderId,
|
|
@@ -234,7 +237,7 @@ import {
|
|
|
234
237
|
visibilityCompareSelectionSchema,
|
|
235
238
|
visibilityReportRequestSchema,
|
|
236
239
|
winnabilityClassSchema
|
|
237
|
-
} from "./chunk-
|
|
240
|
+
} from "./chunk-MHB23E3N.js";
|
|
238
241
|
|
|
239
242
|
// src/cli.ts
|
|
240
243
|
import { pathToFileURL } from "url";
|
|
@@ -784,7 +787,7 @@ function parseDemoTrustedProxies(values) {
|
|
|
784
787
|
async function demoCommand(options) {
|
|
785
788
|
const { host, port } = parseDemoListenOptions(options);
|
|
786
789
|
const trustProxy = parseDemoTrustedProxies(options.trustProxy);
|
|
787
|
-
const { createDemoServer } = await import("./demo-server-
|
|
790
|
+
const { createDemoServer } = await import("./demo-server-WQDHQG6P.js");
|
|
788
791
|
const app = await createDemoServer({ trustProxy });
|
|
789
792
|
let stopping = false;
|
|
790
793
|
const stop = () => {
|
|
@@ -1198,7 +1201,7 @@ No DB writes performed. Re-run without --dry-run to apply.`);
|
|
|
1198
1201
|
}
|
|
1199
1202
|
}
|
|
1200
1203
|
async function backfillInsightsCommand(project2, opts) {
|
|
1201
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
1204
|
+
const { IntelligenceService } = await import("./intelligence-service-JWZRZ6JZ.js");
|
|
1202
1205
|
const config = loadConfig();
|
|
1203
1206
|
const db = createClient(config.database);
|
|
1204
1207
|
migrate(db);
|
|
@@ -5437,8 +5440,99 @@ async function gaSync(project2, opts) {
|
|
|
5437
5440
|
console.log(` AI rows: ${result.aiReferralCount}`);
|
|
5438
5441
|
console.log(` Social rows: ${result.socialReferralCount}`);
|
|
5439
5442
|
console.log(` Period: ${result.days} days${result.clamped ? ` (requested ${result.requestedDays})` : ""}`);
|
|
5443
|
+
const searchLanding = result.measurement.searchLandingPages;
|
|
5444
|
+
if (searchLanding) {
|
|
5445
|
+
console.log(` Search Console landing pages: ${searchLanding.status} (${searchLanding.rowCount} rows)`);
|
|
5446
|
+
if (searchLanding.error) console.log(` Error: ${searchLanding.error}`);
|
|
5447
|
+
}
|
|
5440
5448
|
console.log(` Synced at: ${result.syncedAt}`);
|
|
5441
5449
|
}
|
|
5450
|
+
var SEARCH_LANDING_NOT_AVAILABLE = "n/a";
|
|
5451
|
+
function searchLandingCells(metrics) {
|
|
5452
|
+
return [
|
|
5453
|
+
metrics.organicGoogleSearchClicks.toLocaleString("en-US"),
|
|
5454
|
+
metrics.organicGoogleSearchImpressions.toLocaleString("en-US"),
|
|
5455
|
+
metrics.organicGoogleSearchClickThroughRate === null ? SEARCH_LANDING_NOT_AVAILABLE : formatPercent(metrics.organicGoogleSearchClickThroughRate),
|
|
5456
|
+
metrics.organicGoogleSearchAveragePosition === null ? SEARCH_LANDING_NOT_AVAILABLE : metrics.organicGoogleSearchAveragePosition.toFixed(1),
|
|
5457
|
+
metrics.activeUsers.toLocaleString("en-US")
|
|
5458
|
+
];
|
|
5459
|
+
}
|
|
5460
|
+
async function gaSearchLandingPages(project2, opts) {
|
|
5461
|
+
const client = getClient7();
|
|
5462
|
+
const params = {};
|
|
5463
|
+
if (opts?.window) params.window = opts.window;
|
|
5464
|
+
if (opts?.limit) params.limit = opts.limit;
|
|
5465
|
+
if (opts?.offset) params.offset = opts.offset;
|
|
5466
|
+
const result = await client.gaSearchLandingPages(
|
|
5467
|
+
project2,
|
|
5468
|
+
Object.keys(params).length > 0 ? params : void 0
|
|
5469
|
+
);
|
|
5470
|
+
if (opts?.format === "json") {
|
|
5471
|
+
console.log(JSON.stringify(result, null, 2));
|
|
5472
|
+
return;
|
|
5473
|
+
} else if (opts?.format === "jsonl") {
|
|
5474
|
+
emitJsonl(result.rows.map((row) => ({
|
|
5475
|
+
project: project2,
|
|
5476
|
+
window: result.window,
|
|
5477
|
+
windowStart: result.windowStart,
|
|
5478
|
+
windowEnd: result.windowEnd,
|
|
5479
|
+
...row
|
|
5480
|
+
})));
|
|
5481
|
+
return;
|
|
5482
|
+
}
|
|
5483
|
+
if (result.status === "never-synced") {
|
|
5484
|
+
console.log(`No GA4 Search Console landing-page data for "${project2}" yet. Run "canonry ga sync ${project2}".`);
|
|
5485
|
+
return;
|
|
5486
|
+
}
|
|
5487
|
+
console.log(`Google organic search traffic: landing page + query string (GA4 Search Console link) for "${project2}"`);
|
|
5488
|
+
if (result.windowStart && result.windowEnd) {
|
|
5489
|
+
console.log(`Last ${result.windowDays ?? GA_SEARCH_LANDING_WINDOW_DAYS[result.window]} days: ${result.windowStart} to ${result.windowEnd}${result.timeZone ? ` (${result.timeZone})` : ""}`);
|
|
5490
|
+
}
|
|
5491
|
+
if (result.status === "unavailable") {
|
|
5492
|
+
console.log(`Status: unavailable. GA4 did not return Search Console data: ${result.error ?? "no reason given"}`);
|
|
5493
|
+
console.log(`Link Search Console to this GA4 property (GA4 Admin, Product links, Search Console links), then run "canonry ga sync ${project2}".`);
|
|
5494
|
+
} else if (result.status === "error") {
|
|
5495
|
+
console.log(`Status: the last refresh failed${result.attemptedAt ? ` (${result.attemptedAt})` : ""}: ${result.error ?? "unknown error"}`);
|
|
5496
|
+
}
|
|
5497
|
+
if (result.status !== "ready" && result.total) {
|
|
5498
|
+
console.log(`Showing the snapshot synced ${result.syncedAt ?? "earlier"}.`);
|
|
5499
|
+
}
|
|
5500
|
+
if (!result.total) {
|
|
5501
|
+
console.log("No stored snapshot.");
|
|
5502
|
+
return;
|
|
5503
|
+
}
|
|
5504
|
+
const headers = ["LANDING PAGE", "CLICKS", "IMPRESSIONS", "CTR", "AVG POSITION", "ACTIVE USERS"];
|
|
5505
|
+
const table = [
|
|
5506
|
+
["Total", ...searchLandingCells(result.total)],
|
|
5507
|
+
...result.rows.map((row) => [gaSearchLandingPageLabel(row.landingPage), ...searchLandingCells(row)])
|
|
5508
|
+
];
|
|
5509
|
+
const pageWidth = Math.min(60, Math.max(headers[0].length, ...table.map((row) => row[0].length)));
|
|
5510
|
+
const widths = headers.map((header, index) => index === 0 ? pageWidth : Math.max(header.length, ...table.map((row) => row[index].length)));
|
|
5511
|
+
const line = (cells) => ` ${cells.map((cell2, index) => index === 0 ? (cell2.length > pageWidth ? `${cell2.slice(0, pageWidth - 3)}...` : cell2).padEnd(pageWidth) : cell2.padStart(widths[index])).join(" ")}`;
|
|
5512
|
+
console.log();
|
|
5513
|
+
console.log(line(headers));
|
|
5514
|
+
console.log(` ${widths.map((width) => "\u2500".repeat(width)).join(" ")}`);
|
|
5515
|
+
for (const row of table) console.log(line(row));
|
|
5516
|
+
console.log();
|
|
5517
|
+
if (result.rows.length > 0) {
|
|
5518
|
+
console.log(` Showing ${result.offset + 1}-${result.offset + result.rows.length} of ${result.totalRows} pages.`);
|
|
5519
|
+
} else if (result.totalRows > 0) {
|
|
5520
|
+
console.log(` No landing-page rows at offset ${result.offset} (${result.totalRows} stored).`);
|
|
5521
|
+
}
|
|
5522
|
+
if (!gaSearchLandingHasSearchData(result.total)) {
|
|
5523
|
+
console.log(" No landing pages had Google organic search traffic in this window.");
|
|
5524
|
+
console.log(" If the property should have some, check its Search Console link in GA4 (Admin, Product links, Search Console links).");
|
|
5525
|
+
}
|
|
5526
|
+
if (result.rowsCapped && result.reportRowCount !== null) {
|
|
5527
|
+
console.log(` GA4 reported ${result.reportRowCount} rows; the ${result.totalRows} with the most clicks are stored.`);
|
|
5528
|
+
}
|
|
5529
|
+
if (result.subjectToThresholding) {
|
|
5530
|
+
console.log(" GA4 applied thresholding to this report, so some rows may be withheld.");
|
|
5531
|
+
}
|
|
5532
|
+
if (result.status === "ready" && result.syncedAt) {
|
|
5533
|
+
console.log(` Synced at: ${result.syncedAt}`);
|
|
5534
|
+
}
|
|
5535
|
+
}
|
|
5442
5536
|
async function gaTraffic(project2, opts) {
|
|
5443
5537
|
const client = getClient7();
|
|
5444
5538
|
const params = rangeParams(opts, opts?.limit ? { limit: String(opts.limit) } : void 0);
|
|
@@ -6094,13 +6188,13 @@ var GA_CLI_COMMANDS = [
|
|
|
6094
6188
|
},
|
|
6095
6189
|
{
|
|
6096
6190
|
path: ["ga", "sync"],
|
|
6097
|
-
usage: "canonry ga sync <project> [--days 30] [--only traffic|ai|social] [--format json]",
|
|
6191
|
+
usage: "canonry ga sync <project> [--days 30] [--only traffic|ai|social|search-landing] [--format json]",
|
|
6098
6192
|
options: {
|
|
6099
6193
|
days: stringOption(),
|
|
6100
6194
|
only: stringOption()
|
|
6101
6195
|
},
|
|
6102
6196
|
run: async (input) => {
|
|
6103
|
-
const project2 = requireProject(input, "ga.sync", "canonry ga sync <project> [--days 30] [--only traffic|ai|social] [--format json]");
|
|
6197
|
+
const project2 = requireProject(input, "ga.sync", "canonry ga sync <project> [--days 30] [--only traffic|ai|social|search-landing] [--format json]");
|
|
6104
6198
|
const daysStr = getString(input.values, "days");
|
|
6105
6199
|
const days = daysStr ? parseInt(daysStr, 10) : void 0;
|
|
6106
6200
|
const only = getString(input.values, "only");
|
|
@@ -6132,6 +6226,24 @@ var GA_CLI_COMMANDS = [
|
|
|
6132
6226
|
});
|
|
6133
6227
|
}
|
|
6134
6228
|
},
|
|
6229
|
+
{
|
|
6230
|
+
path: ["ga", "search-landing-pages"],
|
|
6231
|
+
usage: "canonry ga search-landing-pages <project> [--window 7d|28d|90d] [--limit 50] [--offset 0] [--format json|jsonl]",
|
|
6232
|
+
options: {
|
|
6233
|
+
window: stringOption(),
|
|
6234
|
+
limit: stringOption(),
|
|
6235
|
+
offset: stringOption()
|
|
6236
|
+
},
|
|
6237
|
+
run: async (input) => {
|
|
6238
|
+
const project2 = requireProject(input, "ga.search-landing-pages", "canonry ga search-landing-pages <project> [--window 7d|28d|90d] [--limit 50] [--offset 0] [--format json|jsonl]");
|
|
6239
|
+
await gaSearchLandingPages(project2, {
|
|
6240
|
+
window: getString(input.values, "window"),
|
|
6241
|
+
limit: getString(input.values, "limit"),
|
|
6242
|
+
offset: getString(input.values, "offset"),
|
|
6243
|
+
format: input.format
|
|
6244
|
+
});
|
|
6245
|
+
}
|
|
6246
|
+
},
|
|
6135
6247
|
{
|
|
6136
6248
|
path: ["ga", "traffic"],
|
|
6137
6249
|
usage: `canonry ga traffic <project> [--limit 50] ${RANGE_USAGE} [--format json]`,
|
|
@@ -6241,7 +6353,7 @@ var GA_CLI_COMMANDS = [
|
|
|
6241
6353
|
unknownSubcommand(input.positionals[0], {
|
|
6242
6354
|
command: "ga",
|
|
6243
6355
|
usage: "canonry ga <subcommand> <project> [args]",
|
|
6244
|
-
available: ["connect", "disconnect", "status", "properties", "sync", "measurement-analysis", "traffic", "coverage", "ai-referral-history", "ai-referral-daily", "social-referral-history", "session-history", "social-referral-summary", "attribution"]
|
|
6356
|
+
available: ["connect", "disconnect", "status", "properties", "sync", "measurement-analysis", "search-landing-pages", "traffic", "coverage", "ai-referral-history", "ai-referral-daily", "social-referral-history", "session-history", "social-referral-summary", "attribution"]
|
|
6245
6357
|
});
|
|
6246
6358
|
}
|
|
6247
6359
|
}
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
computeFactorAverages,
|
|
6
6
|
layoutSiteCrawlGraphInput,
|
|
7
7
|
persistSiteCrawlGraphLayout
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-C6GWKYGE.js";
|
|
9
9
|
import {
|
|
10
10
|
PACKAGE_VERSION,
|
|
11
11
|
canonryMcpTools
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-FK7AWV57.js";
|
|
13
13
|
import {
|
|
14
14
|
HISTORY_WINDOW_RUNS,
|
|
15
15
|
IntelligenceService,
|
|
@@ -42,6 +42,8 @@ import {
|
|
|
42
42
|
gaDailyTotals,
|
|
43
43
|
gaLeadEventsDaily,
|
|
44
44
|
gaMeasurementSyncStates,
|
|
45
|
+
gaSearchLandingPages,
|
|
46
|
+
gaSearchLandingWindows,
|
|
45
47
|
gaTrafficSnapshots,
|
|
46
48
|
gaTrafficSummaries,
|
|
47
49
|
gaTrafficWindowSummaries,
|
|
@@ -83,7 +85,7 @@ import {
|
|
|
83
85
|
siteCrawlPages,
|
|
84
86
|
siteCrawlSnapshots,
|
|
85
87
|
trafficSources
|
|
86
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-ZQ7C6IFA.js";
|
|
87
89
|
import {
|
|
88
90
|
RunKinds,
|
|
89
91
|
SiteCrawlFetchStates,
|
|
@@ -112,7 +114,7 @@ import {
|
|
|
112
114
|
roundPreservingTotal,
|
|
113
115
|
siteAuditPageFactorSchema,
|
|
114
116
|
wilsonInterval
|
|
115
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-MHB23E3N.js";
|
|
116
118
|
|
|
117
119
|
// src/demo-server.ts
|
|
118
120
|
import { dirname, join as join2 } from "path";
|
|
@@ -1170,6 +1172,7 @@ var DEMO_READ_ROUTES = /* @__PURE__ */ new Set([
|
|
|
1170
1172
|
"/api/v1/projects/:name/ga/attribution-trend",
|
|
1171
1173
|
"/api/v1/projects/:name/ga/coverage",
|
|
1172
1174
|
"/api/v1/projects/:name/ga/measurement-analysis",
|
|
1175
|
+
"/api/v1/projects/:name/ga/search-landing-pages",
|
|
1173
1176
|
"/api/v1/projects/:name/ga/session-history",
|
|
1174
1177
|
"/api/v1/projects/:name/ga/social-referral-history",
|
|
1175
1178
|
"/api/v1/projects/:name/ga/social-referral-trend",
|
|
@@ -2082,6 +2085,16 @@ function seedDemoCore(db, context) {
|
|
|
2082
2085
|
seedDemoAnswerIntelligence(db, context.simple);
|
|
2083
2086
|
}
|
|
2084
2087
|
|
|
2088
|
+
// src/demo/types.ts
|
|
2089
|
+
var DEMO_GA4_PROPERTY_ID = "demo-property";
|
|
2090
|
+
function createDemoSeedContext(now = /* @__PURE__ */ new Date()) {
|
|
2091
|
+
return {
|
|
2092
|
+
now,
|
|
2093
|
+
simple: { id: "demo-project-summit", name: "summit-roofing", displayName: "Summit Roofing", domain: "summit-roofing.example" },
|
|
2094
|
+
portfolio: { id: "demo-project-harbor", name: "harbor-resorts", displayName: "Harbor Resorts", domain: "harbor-resorts.example" }
|
|
2095
|
+
};
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2085
2098
|
// src/demo/seed-site-crawl.ts
|
|
2086
2099
|
var DEMO_AUDIT_FACTORS = [
|
|
2087
2100
|
{ id: "structured-data", name: "Structured Data (JSON-LD)", weight: 12, bias: 4, found: "JSON-LD markup describes this page.", missing: "JSON-LD markup is missing or incomplete.", recommendation: "Add JSON-LD that describes the business and this page." },
|
|
@@ -2794,6 +2807,54 @@ async function seedDemoSignals(db, context) {
|
|
|
2794
2807
|
await seedProjectSignals(db, project, context.now, index);
|
|
2795
2808
|
}
|
|
2796
2809
|
}
|
|
2810
|
+
function seedSearchLandingPages(db, input) {
|
|
2811
|
+
const windows = [["7d", 7, 1], ["28d", 28, 4], ["90d", 90, 12]];
|
|
2812
|
+
for (const [windowKey, days, scale] of windows) {
|
|
2813
|
+
const clicks = (140 + input.variant * 25) * scale;
|
|
2814
|
+
const impressions = (5200 + input.variant * 640) * scale;
|
|
2815
|
+
db.insert(gaSearchLandingWindows).values({
|
|
2816
|
+
id: `${input.prefix}-ga-search-window-${windowKey}`,
|
|
2817
|
+
projectId: input.projectId,
|
|
2818
|
+
propertyId: DEMO_GA4_PROPERTY_ID,
|
|
2819
|
+
windowKey,
|
|
2820
|
+
periodStart: day(input.now, -days),
|
|
2821
|
+
periodEnd: day(input.now, -1),
|
|
2822
|
+
timeZone: "UTC",
|
|
2823
|
+
totalClicks: clicks,
|
|
2824
|
+
totalImpressions: impressions,
|
|
2825
|
+
totalCtr: clicks / impressions,
|
|
2826
|
+
totalAveragePosition: 7.4 - input.variant * 0.6,
|
|
2827
|
+
totalActiveUsers: (170 + input.variant * 30) * scale,
|
|
2828
|
+
reportRowCount: 24,
|
|
2829
|
+
rowsCapped: true,
|
|
2830
|
+
syncedAt: input.nowIso,
|
|
2831
|
+
syncRunId: input.syncRunId,
|
|
2832
|
+
createdAt: input.nowIso
|
|
2833
|
+
}).run();
|
|
2834
|
+
const pages = [
|
|
2835
|
+
["/", 0.55, 0.32, 5.1],
|
|
2836
|
+
["/services/", 0.21, 0.27, 7.8]
|
|
2837
|
+
];
|
|
2838
|
+
for (const [landingPage, clickShare, impressionShare, position] of pages) {
|
|
2839
|
+
const pageClicks = Math.round(clicks * clickShare);
|
|
2840
|
+
const pageImpressions = Math.round(impressions * impressionShare);
|
|
2841
|
+
db.insert(gaSearchLandingPages).values({
|
|
2842
|
+
id: `${input.prefix}-ga-search-page-${windowKey}-${landingPage}`,
|
|
2843
|
+
projectId: input.projectId,
|
|
2844
|
+
windowKey,
|
|
2845
|
+
landingPage,
|
|
2846
|
+
clicks: pageClicks,
|
|
2847
|
+
impressions: pageImpressions,
|
|
2848
|
+
ctr: pageClicks / pageImpressions,
|
|
2849
|
+
averagePosition: position,
|
|
2850
|
+
activeUsers: Math.round(pageClicks * 1.2),
|
|
2851
|
+
syncedAt: input.nowIso,
|
|
2852
|
+
syncRunId: input.syncRunId,
|
|
2853
|
+
createdAt: input.nowIso
|
|
2854
|
+
}).run();
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2797
2858
|
async function seedProjectSignals(db, project, now, variant) {
|
|
2798
2859
|
const nowIso = now.toISOString();
|
|
2799
2860
|
const prefix = `demo-signals-${project.id}`;
|
|
@@ -2834,7 +2895,8 @@ async function seedProjectSignals(db, project, now, variant) {
|
|
|
2834
2895
|
db.insert(gscUrlInspections).values({ id: `${prefix}-gsc-inspection`, projectId: project.id, syncRunId, url: `${root}services/`, indexingState: "INDEXING_ALLOWED", verdict: "PASS", coverageState: "Submitted and indexed", pageFetchState: "SUCCESSFUL", robotsTxtState: "ALLOWED", crawlTime: nowIso, lastCrawlResult: "SUCCESSFUL", isMobileFriendly: true, richResults: ["Sample FAQ"], referringUrls: [root], inspectedAt: nowIso, createdAt: nowIso }).run();
|
|
2835
2896
|
db.insert(bingKeywordStats).values(searchTerms.map((query, i) => ({ id: `${prefix}-bing-keyword-${i}`, projectId: project.id, query, impressions: 310 - i * 70, clicks: 22 - i * 4, ctr: "0.071", averagePosition: String(6 + i), syncedAt: nowIso, createdAt: nowIso }))).run();
|
|
2836
2897
|
db.insert(bingUrlInspections).values({ id: `${prefix}-bing-inspection`, projectId: project.id, url: root, httpCode: 200, inIndex: true, lastCrawledDate: dates.at(-2), inIndexDate: dates.at(-8), inspectedAt: nowIso, syncRunId, createdAt: nowIso, documentSize: 24120, anchorCount: 18, discoveryDate: dates[0] }).run();
|
|
2837
|
-
db.insert(gaMeasurementSyncStates).values({ projectId: project.id, acquisitionStatus: "ready", acquisitionSyncedAt: nowIso, leadStatus: "ready", leadSyncedAt: nowIso, leadAttributionScope: "landing-page", updatedAt: nowIso }).run();
|
|
2898
|
+
db.insert(gaMeasurementSyncStates).values({ projectId: project.id, acquisitionStatus: "ready", acquisitionSyncedAt: nowIso, leadStatus: "ready", leadSyncedAt: nowIso, leadAttributionScope: "landing-page", searchLandingStatus: "ready", searchLandingSyncedAt: nowIso, searchLandingAttemptedAt: nowIso, updatedAt: nowIso }).run();
|
|
2899
|
+
seedSearchLandingPages(db, { projectId: project.id, prefix, syncRunId, nowIso, now, variant });
|
|
2838
2900
|
db.insert(gaTrafficSummaries).values({ id: `${prefix}-ga-summary`, projectId: project.id, periodStart: dates[0], periodEnd: dates.at(-1), totalSessions: 1610, totalOrganicSessions: 980, totalUsers: 1214, syncedAt: nowIso, syncRunId }).run();
|
|
2839
2901
|
db.insert(gaTrafficWindowSummaries).values({ id: `${prefix}-ga-window`, projectId: project.id, windowKey: "30d", periodStart: dates[0], periodEnd: dates.at(-1), totalSessions: 1610, totalOrganicSessions: 980, totalDirectSessions: 284, totalUsers: 1214, syncedAt: nowIso, syncRunId }).run();
|
|
2840
2902
|
const inventory = variant === 0 ? summitRoofingInventory() : harborResortsInventory();
|
|
@@ -2915,7 +2977,7 @@ function demoReadOptions(db, context) {
|
|
|
2915
2977
|
ga4CredentialStore: {
|
|
2916
2978
|
getConnection: (projectName) => {
|
|
2917
2979
|
const project = [context.simple, context.portfolio].find((item) => item.name === projectName);
|
|
2918
|
-
return project ? { projectName, propertyId:
|
|
2980
|
+
return project ? { projectName, propertyId: DEMO_GA4_PROPERTY_ID, clientEmail: "sample@analytics.example", privateKey: "", createdAt: context.now.toISOString(), updatedAt: context.now.toISOString() } : void 0;
|
|
2919
2981
|
},
|
|
2920
2982
|
upsertConnection: refuseMutation,
|
|
2921
2983
|
deleteConnection: refuseMutation
|
|
@@ -2953,15 +3015,6 @@ function demoReadOptions(db, context) {
|
|
|
2953
3015
|
};
|
|
2954
3016
|
}
|
|
2955
3017
|
|
|
2956
|
-
// src/demo/types.ts
|
|
2957
|
-
function createDemoSeedContext(now = /* @__PURE__ */ new Date()) {
|
|
2958
|
-
return {
|
|
2959
|
-
now,
|
|
2960
|
-
simple: { id: "demo-project-summit", name: "summit-roofing", displayName: "Summit Roofing", domain: "summit-roofing.example" },
|
|
2961
|
-
portfolio: { id: "demo-project-harbor", name: "harbor-resorts", displayName: "Harbor Resorts", domain: "harbor-resorts.example" }
|
|
2962
|
-
};
|
|
2963
|
-
}
|
|
2964
|
-
|
|
2965
3018
|
// src/demo-server.ts
|
|
2966
3019
|
async function createDemoServer(options = {}) {
|
|
2967
3020
|
const db = createClient(":memory:");
|
package/dist/index.js
CHANGED
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ORA5R7QM.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-PLS4EM2Y.js";
|
|
10
|
+
import "./chunk-C6GWKYGE.js";
|
|
11
|
+
import "./chunk-FK7AWV57.js";
|
|
12
|
+
import "./chunk-ZQ7C6IFA.js";
|
|
13
|
+
import "./chunk-MHB23E3N.js";
|
|
14
14
|
export {
|
|
15
15
|
GoogleMarketingRuntimeError,
|
|
16
16
|
createGoogleMarketingCredentialStore,
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OPJCFDNR.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-PLS4EM2Y.js";
|
|
8
|
+
import "./chunk-FK7AWV57.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
|
11
11
|
updateCheckEnvOptOut
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-MHB23E3N.js";
|
|
13
13
|
|
|
14
14
|
// src/mcp/cli.ts
|
|
15
15
|
import { randomUUID } from "crypto";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.17.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": [
|
|
@@ -87,32 +87,32 @@
|
|
|
87
87
|
"tsx": "^4.19.0",
|
|
88
88
|
"@ainyc/canonry-web": "0.0.0",
|
|
89
89
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
90
|
-
"@ainyc/canonry-api-client": "0.0.0",
|
|
91
90
|
"@ainyc/canonry-config": "0.0.0",
|
|
92
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
93
91
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
92
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
93
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
94
94
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
95
95
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
96
|
-
"@ainyc/canonry-integration-
|
|
96
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
97
97
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
98
98
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
99
|
-
"@ainyc/canonry-integration-google-
|
|
99
|
+
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
100
|
+
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
100
101
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
102
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
101
103
|
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
102
|
-
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
103
104
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
104
105
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
105
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
106
106
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
107
107
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
108
|
-
"@ainyc/canonry-
|
|
109
|
-
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
108
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
110
109
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
111
110
|
"@ainyc/canonry-provider-muse": "0.0.0",
|
|
112
|
-
"@ainyc/canonry-provider-
|
|
111
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
113
112
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
114
|
-
"@ainyc/canonry-
|
|
115
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
113
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
114
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
115
|
+
"@ainyc/canonry-integration-typesafe": "0.0.0"
|
|
116
116
|
},
|
|
117
117
|
"scripts": {
|
|
118
118
|
"build": "pnpm run build:cli && pnpm run build:web",
|