@canonry/canonry 4.123.0 → 4.124.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/{AuditHistoryPanel-BVQMDIhQ.js → AuditHistoryPanel-fPBADGsr.js} +1 -1
- package/assets/assets/{BacklinksPage-nrHT9VMG.js → BacklinksPage-DKer7s8M.js} +1 -1
- package/assets/assets/{ChartPrimitives-_8qLsQzI.js → ChartPrimitives-0DFDFhCZ.js} +1 -1
- package/assets/assets/{HistoryPage-DqsKKdyy.js → HistoryPage-BTkTlXg0.js} +1 -1
- package/assets/assets/{ProjectPage-GyKoQUv_.js → ProjectPage-BzqDCkp2.js} +1 -1
- package/assets/assets/{RunRow-BRZZcSjQ.js → RunRow-DyIeH4_d.js} +1 -1
- package/assets/assets/{RunsPage-24aI8DKF.js → RunsPage-KVu_37ds.js} +1 -1
- package/assets/assets/{SettingsPage-BaNeTG1i.js → SettingsPage-CCLXSBpq.js} +1 -1
- package/assets/assets/{TrafficPage-ByvcLSjv.js → TrafficPage-BH7a0sS2.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-B-siTXVg.js → TrafficSourceDetailPage-kIlf0kCe.js} +1 -1
- package/assets/assets/{arrow-left-CBh1cZNH.js → arrow-left-jhivZs4g.js} +1 -1
- package/assets/assets/{extract-error-message-DJZCPudR.js → extract-error-message-XU_cbcLD.js} +1 -1
- package/assets/assets/{index-mzLganDP.js → index-CqFSTLK5.js} +7 -7
- package/assets/assets/{trash-2-Bh-Yvkgc.js → trash-2-CcmHLt5u.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-JYBNBK25.js → chunk-4D2XUMMV.js} +4 -4
- package/dist/{chunk-4AZ7VES6.js → chunk-BGLBWFMV.js} +120 -18
- package/dist/{chunk-MMFSI3OG.js → chunk-SLCGTOKT.js} +17 -1
- package/dist/{chunk-HJIIJI7K.js → chunk-WGGB7QBD.js} +1 -1
- package/dist/cli.js +11 -5
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-K35EN43I.js → intelligence-service-SACHNNCT.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c}from"./index-
|
|
1
|
+
import{c}from"./index-CqFSTLK5.js";const a=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],h=c("circle-check",a);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],n=c("circle-question-mark",e);const o=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=c("download",o);const t=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],r=c("trash-2",t);export{h as C,s as D,r as T,n as a};
|
package/assets/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
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-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-CqFSTLK5.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Be8JdV5M.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-CQ77EO2y.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-DSxTZhaH.js">
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-WGGB7QBD.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -115,7 +115,7 @@ import {
|
|
|
115
115
|
siteAuditPages,
|
|
116
116
|
siteAuditSnapshots,
|
|
117
117
|
usageCounters
|
|
118
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-BGLBWFMV.js";
|
|
119
119
|
import {
|
|
120
120
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
121
121
|
AGENT_PROVIDER_IDS,
|
|
@@ -185,7 +185,7 @@ import {
|
|
|
185
185
|
validationError,
|
|
186
186
|
winnabilityClassLabel,
|
|
187
187
|
withRetry
|
|
188
|
-
} from "./chunk-
|
|
188
|
+
} from "./chunk-SLCGTOKT.js";
|
|
189
189
|
|
|
190
190
|
// src/telemetry.ts
|
|
191
191
|
import crypto from "crypto";
|
|
@@ -6901,7 +6901,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
6901
6901
|
return result;
|
|
6902
6902
|
}
|
|
6903
6903
|
async function backfillInsightsCommand(project, opts) {
|
|
6904
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
6904
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-SACHNNCT.js");
|
|
6905
6905
|
const config = loadConfig();
|
|
6906
6906
|
const db = createClient(config.database);
|
|
6907
6907
|
migrate(db);
|
|
@@ -141,6 +141,7 @@ import {
|
|
|
141
141
|
classifyTrafficPath,
|
|
142
142
|
clusterByCosine,
|
|
143
143
|
coerceSkillManifest,
|
|
144
|
+
compactDateToIso,
|
|
144
145
|
competitorBatchRequestSchema,
|
|
145
146
|
competitorDtoSchema,
|
|
146
147
|
computeDedupSimilarityStats,
|
|
@@ -334,7 +335,7 @@ import {
|
|
|
334
335
|
wordpressSchemaDeployResultDtoSchema,
|
|
335
336
|
wordpressSchemaStatusResultDtoSchema,
|
|
336
337
|
wordpressStatusDtoSchema
|
|
337
|
-
} from "./chunk-
|
|
338
|
+
} from "./chunk-SLCGTOKT.js";
|
|
338
339
|
|
|
339
340
|
// src/intelligence-service.ts
|
|
340
341
|
import { eq as eq41, desc as desc18, asc as asc9, and as and32, ne as ne6, or as or8, inArray as inArray15, gte as gte10, lte as lte6 } from "drizzle-orm";
|
|
@@ -378,6 +379,7 @@ __export(schema_exports, {
|
|
|
378
379
|
domainClassifications: () => domainClassifications,
|
|
379
380
|
gaAiReferrals: () => gaAiReferrals,
|
|
380
381
|
gaConnections: () => gaConnections,
|
|
382
|
+
gaDailyTotals: () => gaDailyTotals,
|
|
381
383
|
gaSocialReferrals: () => gaSocialReferrals,
|
|
382
384
|
gaTrafficSnapshots: () => gaTrafficSnapshots,
|
|
383
385
|
gaTrafficSummaries: () => gaTrafficSummaries,
|
|
@@ -823,6 +825,20 @@ var gaTrafficSnapshots = sqliteTable("ga_traffic_snapshots", {
|
|
|
823
825
|
index("idx_ga_traffic_page_normalized").on(table.projectId, table.date, table.landingPageNormalized),
|
|
824
826
|
index("idx_ga_traffic_run").on(table.syncRunId)
|
|
825
827
|
]);
|
|
828
|
+
var gaDailyTotals = sqliteTable("ga_daily_totals", {
|
|
829
|
+
id: text("id").primaryKey(),
|
|
830
|
+
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
831
|
+
date: text("date").notNull(),
|
|
832
|
+
sessions: integer("sessions").notNull().default(0),
|
|
833
|
+
users: integer("users").notNull().default(0),
|
|
834
|
+
syncedAt: text("synced_at").notNull(),
|
|
835
|
+
syncRunId: text("sync_run_id").references(() => runs.id, { onDelete: "cascade" }),
|
|
836
|
+
createdAt: text("created_at").notNull()
|
|
837
|
+
}, (table) => [
|
|
838
|
+
uniqueIndex("idx_ga_daily_totals_project_date").on(table.projectId, table.date),
|
|
839
|
+
index("idx_ga_daily_totals_project").on(table.projectId),
|
|
840
|
+
index("idx_ga_daily_totals_run").on(table.syncRunId)
|
|
841
|
+
]);
|
|
826
842
|
var gaAiReferrals = sqliteTable("ga_ai_referrals", {
|
|
827
843
|
id: text("id").primaryKey(),
|
|
828
844
|
projectId: text("project_id").notNull().references(() => projects.id, { onDelete: "cascade" }),
|
|
@@ -3929,6 +3945,31 @@ var MIGRATION_VERSIONS = [
|
|
|
3929
3945
|
run: (tx) => {
|
|
3930
3946
|
backfillQuerySnapshotServedModel(tx);
|
|
3931
3947
|
}
|
|
3948
|
+
},
|
|
3949
|
+
{
|
|
3950
|
+
// `users` is not additive across landing pages — one visitor who lands on
|
|
3951
|
+
// three pages is one user but contributes to three `ga_traffic_snapshots`
|
|
3952
|
+
// rows. Summing that dimensioned table overcounts the day. This table
|
|
3953
|
+
// stores the same day fetched with NO landing-page dimension, so GA does
|
|
3954
|
+
// the dedup and the stored number matches the GA UI. Same shape and
|
|
3955
|
+
// rationale as `gsc_daily_totals`.
|
|
3956
|
+
version: 106,
|
|
3957
|
+
name: "ga-daily-totals",
|
|
3958
|
+
statements: [
|
|
3959
|
+
`CREATE TABLE IF NOT EXISTS ga_daily_totals (
|
|
3960
|
+
id TEXT PRIMARY KEY,
|
|
3961
|
+
project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
3962
|
+
date TEXT NOT NULL,
|
|
3963
|
+
sessions INTEGER NOT NULL DEFAULT 0,
|
|
3964
|
+
users INTEGER NOT NULL DEFAULT 0,
|
|
3965
|
+
synced_at TEXT NOT NULL,
|
|
3966
|
+
sync_run_id TEXT REFERENCES runs(id) ON DELETE CASCADE,
|
|
3967
|
+
created_at TEXT NOT NULL
|
|
3968
|
+
)`,
|
|
3969
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_ga_daily_totals_project_date ON ga_daily_totals(project_id, date)`,
|
|
3970
|
+
`CREATE INDEX IF NOT EXISTS idx_ga_daily_totals_project ON ga_daily_totals(project_id)`,
|
|
3971
|
+
`CREATE INDEX IF NOT EXISTS idx_ga_daily_totals_run ON ga_daily_totals(sync_run_id)`
|
|
3972
|
+
]
|
|
3932
3973
|
}
|
|
3933
3974
|
];
|
|
3934
3975
|
function rebuildBacklinkTableWithSource(tx, table) {
|
|
@@ -22475,9 +22516,7 @@ async function fetchTrafficByLandingPage(accessToken, propertyId, days) {
|
|
|
22475
22516
|
row.directSessions = directMap.get(key) ?? 0;
|
|
22476
22517
|
}
|
|
22477
22518
|
for (const row of rows) {
|
|
22478
|
-
|
|
22479
|
-
row.date = `${row.date.slice(0, 4)}-${row.date.slice(4, 6)}-${row.date.slice(6, 8)}`;
|
|
22480
|
-
}
|
|
22519
|
+
row.date = compactDateToIso(row.date);
|
|
22481
22520
|
}
|
|
22482
22521
|
ga4Log("info", "fetch-traffic.done", { propertyId, rowCount: rows.length });
|
|
22483
22522
|
return rows;
|
|
@@ -22544,6 +22583,28 @@ async function fetchAggregateSummary(accessToken, propertyId, days) {
|
|
|
22544
22583
|
ga4Log("info", "fetch-aggregate.done", { propertyId, ...summary });
|
|
22545
22584
|
return summary;
|
|
22546
22585
|
}
|
|
22586
|
+
async function fetchDailyTotals(accessToken, propertyId, days) {
|
|
22587
|
+
validateAccessToken2(accessToken);
|
|
22588
|
+
validatePropertyId(propertyId);
|
|
22589
|
+
const syncDays = Math.min(Math.max(1, days ?? GA4_DEFAULT_SYNC_DAYS), GA4_MAX_SYNC_DAYS);
|
|
22590
|
+
const endDate = /* @__PURE__ */ new Date();
|
|
22591
|
+
const startDate = /* @__PURE__ */ new Date();
|
|
22592
|
+
startDate.setDate(startDate.getDate() - syncDays);
|
|
22593
|
+
ga4Log("info", "fetch-daily-totals.start", { propertyId, days: syncDays });
|
|
22594
|
+
const res = await runReport(accessToken, propertyId, {
|
|
22595
|
+
dateRanges: [{ startDate: formatDate2(startDate), endDate: formatDate2(endDate) }],
|
|
22596
|
+
dimensions: [{ name: GA4_DIMENSIONS.date }],
|
|
22597
|
+
metrics: [{ name: GA4_METRICS.sessions }, { name: GA4_METRICS.totalUsers }],
|
|
22598
|
+
limit: syncDays + 1
|
|
22599
|
+
});
|
|
22600
|
+
const rows = (res.rows ?? []).map((row) => ({
|
|
22601
|
+
date: compactDateToIso(row.dimensionValues[0]?.value ?? ""),
|
|
22602
|
+
sessions: parseInt(row.metricValues[0]?.value ?? "0", 10) || 0,
|
|
22603
|
+
users: parseInt(row.metricValues[1]?.value ?? "0", 10) || 0
|
|
22604
|
+
})).filter((row) => row.date.length > 0);
|
|
22605
|
+
ga4Log("info", "fetch-daily-totals.done", { propertyId, days: syncDays, rows: rows.length });
|
|
22606
|
+
return rows;
|
|
22607
|
+
}
|
|
22547
22608
|
var WINDOW_DAYS = { "7d": 7, "30d": 30, "90d": 90 };
|
|
22548
22609
|
async function fetchWindowSummary(accessToken, propertyId, windowKey) {
|
|
22549
22610
|
validateAccessToken2(accessToken);
|
|
@@ -22691,9 +22752,7 @@ async function fetchAiReferrals(accessToken, propertyId, days) {
|
|
|
22691
22752
|
}
|
|
22692
22753
|
const dedupedRows = [...deduped.values()];
|
|
22693
22754
|
for (const row of dedupedRows) {
|
|
22694
|
-
|
|
22695
|
-
row.date = `${row.date.slice(0, 4)}-${row.date.slice(4, 6)}-${row.date.slice(6, 8)}`;
|
|
22696
|
-
}
|
|
22755
|
+
row.date = compactDateToIso(row.date);
|
|
22697
22756
|
}
|
|
22698
22757
|
ga4Log("info", "fetch-ai-referrals.done", { propertyId, rowCount: dedupedRows.length });
|
|
22699
22758
|
return dedupedRows;
|
|
@@ -22754,9 +22813,7 @@ async function fetchSocialReferrals(accessToken, propertyId, days) {
|
|
|
22754
22813
|
if (pageRows.length < PAGE_SIZE || offset >= totalRows) break;
|
|
22755
22814
|
}
|
|
22756
22815
|
for (const row of rows) {
|
|
22757
|
-
|
|
22758
|
-
row.date = `${row.date.slice(0, 4)}-${row.date.slice(4, 6)}-${row.date.slice(6, 8)}`;
|
|
22759
|
-
}
|
|
22816
|
+
row.date = compactDateToIso(row.date);
|
|
22760
22817
|
}
|
|
22761
22818
|
ga4Log("info", "fetch-social-referrals.done", { propertyId, rowCount: rows.length });
|
|
22762
22819
|
return rows;
|
|
@@ -29234,6 +29291,23 @@ async function cdpRoutes(app, opts) {
|
|
|
29234
29291
|
// ../api-routes/src/ga.ts
|
|
29235
29292
|
import crypto24 from "crypto";
|
|
29236
29293
|
import { eq as eq29, desc as desc13, and as and23, sql as sql12 } from "drizzle-orm";
|
|
29294
|
+
|
|
29295
|
+
// ../api-routes/src/ga-session-history.ts
|
|
29296
|
+
function buildSessionHistory(landingPageDays, dailyTotals) {
|
|
29297
|
+
const totalsByDate = new Map(dailyTotals.map((row) => [row.date, row.users]));
|
|
29298
|
+
return landingPageDays.map((day) => {
|
|
29299
|
+
const deduplicated = totalsByDate.get(day.date);
|
|
29300
|
+
return {
|
|
29301
|
+
date: day.date,
|
|
29302
|
+
sessions: day.sessions,
|
|
29303
|
+
organicSessions: day.organicSessions,
|
|
29304
|
+
users: deduplicated ?? day.users,
|
|
29305
|
+
usersSource: deduplicated === void 0 ? "landing-page-sum" : "deduplicated"
|
|
29306
|
+
};
|
|
29307
|
+
});
|
|
29308
|
+
}
|
|
29309
|
+
|
|
29310
|
+
// ../api-routes/src/ga.ts
|
|
29237
29311
|
function gaLog(level, action, ctx) {
|
|
29238
29312
|
const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
|
|
29239
29313
|
const stream = level === "error" ? process.stderr : process.stdout;
|
|
@@ -29512,6 +29586,7 @@ async function ga4Routes(app, opts) {
|
|
|
29512
29586
|
}
|
|
29513
29587
|
app.db.delete(gaTrafficSnapshots).where(eq29(gaTrafficSnapshots.projectId, project.id)).run();
|
|
29514
29588
|
app.db.delete(gaTrafficSummaries).where(eq29(gaTrafficSummaries.projectId, project.id)).run();
|
|
29589
|
+
app.db.delete(gaDailyTotals).where(eq29(gaDailyTotals.projectId, project.id)).run();
|
|
29515
29590
|
app.db.delete(gaAiReferrals).where(eq29(gaAiReferrals.projectId, project.id)).run();
|
|
29516
29591
|
app.db.delete(gaSocialReferrals).where(eq29(gaSocialReferrals.projectId, project.id)).run();
|
|
29517
29592
|
const propertyId = saConn?.propertyId ?? oauthConn?.propertyId ?? null;
|
|
@@ -29576,7 +29651,8 @@ async function ga4Routes(app, opts) {
|
|
|
29576
29651
|
const WINDOW_KEYS = ["7d", "30d", "90d"];
|
|
29577
29652
|
const fetches = [
|
|
29578
29653
|
fetchAggregateSummary(accessToken, propertyId, days),
|
|
29579
|
-
...WINDOW_KEYS.map((w) => fetchWindowSummary(accessToken, propertyId, w))
|
|
29654
|
+
...WINDOW_KEYS.map((w) => fetchWindowSummary(accessToken, propertyId, w)),
|
|
29655
|
+
fetchDailyTotals(accessToken, propertyId, days)
|
|
29580
29656
|
];
|
|
29581
29657
|
if (syncTraffic) fetches.push(fetchTrafficByLandingPage(accessToken, propertyId, days));
|
|
29582
29658
|
if (syncAi) fetches.push(fetchAiReferrals(accessToken, propertyId, days));
|
|
@@ -29584,7 +29660,8 @@ async function ga4Routes(app, opts) {
|
|
|
29584
29660
|
const results = await Promise.all(fetches);
|
|
29585
29661
|
const summary = results[0];
|
|
29586
29662
|
const windowSummaries = results.slice(1, 1 + WINDOW_KEYS.length);
|
|
29587
|
-
|
|
29663
|
+
const dailyTotals = results[1 + WINDOW_KEYS.length];
|
|
29664
|
+
let idx = 2 + WINDOW_KEYS.length;
|
|
29588
29665
|
if (syncTraffic) {
|
|
29589
29666
|
rows = results[idx++];
|
|
29590
29667
|
}
|
|
@@ -29620,6 +29697,25 @@ async function ga4Routes(app, opts) {
|
|
|
29620
29697
|
}).run();
|
|
29621
29698
|
}
|
|
29622
29699
|
}
|
|
29700
|
+
tx.delete(gaDailyTotals).where(
|
|
29701
|
+
and23(
|
|
29702
|
+
eq29(gaDailyTotals.projectId, project.id),
|
|
29703
|
+
sql12`${gaDailyTotals.date} >= ${summary.periodStart}`,
|
|
29704
|
+
sql12`${gaDailyTotals.date} <= ${summary.periodEnd}`
|
|
29705
|
+
)
|
|
29706
|
+
).run();
|
|
29707
|
+
for (const row of dailyTotals) {
|
|
29708
|
+
tx.insert(gaDailyTotals).values({
|
|
29709
|
+
id: crypto24.randomUUID(),
|
|
29710
|
+
projectId: project.id,
|
|
29711
|
+
date: row.date,
|
|
29712
|
+
sessions: row.sessions,
|
|
29713
|
+
users: row.users,
|
|
29714
|
+
syncedAt: now,
|
|
29715
|
+
syncRunId: runId,
|
|
29716
|
+
createdAt: now
|
|
29717
|
+
}).run();
|
|
29718
|
+
}
|
|
29623
29719
|
if (syncAi) {
|
|
29624
29720
|
tx.delete(gaAiReferrals).where(
|
|
29625
29721
|
and23(
|
|
@@ -30116,12 +30212,18 @@ async function ga4Routes(app, opts) {
|
|
|
30116
30212
|
organicSessions: sql12`SUM(${gaTrafficSnapshots.organicSessions})`,
|
|
30117
30213
|
users: sql12`SUM(${gaTrafficSnapshots.users})`
|
|
30118
30214
|
}).from(gaTrafficSnapshots).where(and23(...conditions)).groupBy(gaTrafficSnapshots.date).orderBy(gaTrafficSnapshots.date).all();
|
|
30119
|
-
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30215
|
+
const totalConditions = [eq29(gaDailyTotals.projectId, project.id)];
|
|
30216
|
+
if (cutoffDate) totalConditions.push(sql12`${gaDailyTotals.date} >= ${cutoffDate}`);
|
|
30217
|
+
const totals = app.db.select({ date: gaDailyTotals.date, users: gaDailyTotals.users }).from(gaDailyTotals).where(and23(...totalConditions)).all();
|
|
30218
|
+
return buildSessionHistory(
|
|
30219
|
+
rows.map((r) => ({
|
|
30220
|
+
date: r.date,
|
|
30221
|
+
sessions: r.sessions ?? 0,
|
|
30222
|
+
organicSessions: r.organicSessions ?? 0,
|
|
30223
|
+
users: r.users ?? 0
|
|
30224
|
+
})),
|
|
30225
|
+
totals
|
|
30226
|
+
);
|
|
30125
30227
|
});
|
|
30126
30228
|
app.get("/projects/:name/ga/coverage", async (request, _reply) => {
|
|
30127
30229
|
const project = resolveProject(app.db, request.params.name);
|
|
@@ -867,6 +867,10 @@ function formatWindowCountDelta(d, countLabel, windowLabel) {
|
|
|
867
867
|
const sign = d.deltaAbs > 0 ? "+" : "";
|
|
868
868
|
return `${sign}${formatNumber(Math.round(d.deltaAbs))} ${countLabel} ${windowLabel}`;
|
|
869
869
|
}
|
|
870
|
+
function compactDateToIso(value) {
|
|
871
|
+
if (value.length !== 8 || !/^\d{8}$/.test(value)) return value;
|
|
872
|
+
return `${value.slice(0, 4)}-${value.slice(4, 6)}-${value.slice(6, 8)}`;
|
|
873
|
+
}
|
|
870
874
|
|
|
871
875
|
// ../contracts/src/model-pointers.ts
|
|
872
876
|
var modelPointerEventKindSchema = z7.enum(["introduced", "repointed", "retired"]);
|
|
@@ -3908,7 +3912,18 @@ var ga4SessionHistoryEntrySchema = z24.object({
|
|
|
3908
3912
|
date: z24.string(),
|
|
3909
3913
|
sessions: z24.number(),
|
|
3910
3914
|
organicSessions: z24.number(),
|
|
3911
|
-
|
|
3915
|
+
/**
|
|
3916
|
+
* Unique visitors for the day. Deduplicated by GA when `usersSource` is
|
|
3917
|
+
* `deduplicated`; a landing-page sum (which overcounts multi-page visitors)
|
|
3918
|
+
* for days synced before per-day totals were captured.
|
|
3919
|
+
*/
|
|
3920
|
+
users: z24.number(),
|
|
3921
|
+
/**
|
|
3922
|
+
* How `users` was derived. `deduplicated` matches the GA UI's active users;
|
|
3923
|
+
* `landing-page-sum` is the legacy overcount kept so historical days still
|
|
3924
|
+
* render. Never compare the two across a series without saying which is which.
|
|
3925
|
+
*/
|
|
3926
|
+
usersSource: z24.enum(["deduplicated", "landing-page-sum"])
|
|
3912
3927
|
});
|
|
3913
3928
|
|
|
3914
3929
|
// ../contracts/src/answer-visibility.ts
|
|
@@ -7140,6 +7155,7 @@ export {
|
|
|
7140
7155
|
formatDeltaCopy,
|
|
7141
7156
|
formatAverageDelta,
|
|
7142
7157
|
formatWindowCountDelta,
|
|
7158
|
+
compactDateToIso,
|
|
7143
7159
|
evaluateModelPointerExposure,
|
|
7144
7160
|
buildModelChangeNotice,
|
|
7145
7161
|
googleConnectionDtoSchema,
|
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setTelemetrySource,
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackEvent
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-4D2XUMMV.js";
|
|
33
33
|
import {
|
|
34
34
|
CliError,
|
|
35
35
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
saveConfig,
|
|
47
47
|
saveConfigPatch,
|
|
48
48
|
usageError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-WGGB7QBD.js";
|
|
50
50
|
import {
|
|
51
51
|
apiKeys,
|
|
52
52
|
createClient,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
projects,
|
|
55
55
|
queries,
|
|
56
56
|
renderReportHtml
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-BGLBWFMV.js";
|
|
58
58
|
import {
|
|
59
59
|
AdsOperationKinds,
|
|
60
60
|
AdsOperationStates,
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
providerQuotaPolicySchema,
|
|
96
96
|
resolveProviderInput,
|
|
97
97
|
winnabilityClassSchema
|
|
98
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-SLCGTOKT.js";
|
|
99
99
|
|
|
100
100
|
// src/cli.ts
|
|
101
101
|
import { pathToFileURL } from "url";
|
|
@@ -3763,10 +3763,16 @@ async function gaSessionHistory(project, opts) {
|
|
|
3763
3763
|
console.log(` ${"DATE".padEnd(dateWidth)} ${"SESSIONS".padEnd(10)}${"ORGANIC".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
3764
3764
|
console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
3765
3765
|
for (const row of result) {
|
|
3766
|
+
const users = row.usersSource === "deduplicated" ? String(row.users) : `${row.users}*`;
|
|
3766
3767
|
console.log(
|
|
3767
|
-
` ${row.date.padEnd(dateWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}${
|
|
3768
|
+
` ${row.date.padEnd(dateWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}${users.padEnd(8)}`
|
|
3768
3769
|
);
|
|
3769
3770
|
}
|
|
3771
|
+
if (result.some((row) => row.usersSource !== "deduplicated")) {
|
|
3772
|
+
console.log("\n * Visitor count is approximate \u2014 it adds up each page a visitor landed on,");
|
|
3773
|
+
console.log(" so someone who read several pages is counted more than once. Run");
|
|
3774
|
+
console.log(` "canonry ga sync ${project}" to replace these with exact counts.`);
|
|
3775
|
+
}
|
|
3770
3776
|
}
|
|
3771
3777
|
async function gaCoverage(project, format) {
|
|
3772
3778
|
const client = getClient6();
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4D2XUMMV.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-WGGB7QBD.js";
|
|
7
|
+
import "./chunk-BGLBWFMV.js";
|
|
8
|
+
import "./chunk-SLCGTOKT.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|
package/dist/mcp.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
PACKAGE_VERSION,
|
|
4
4
|
canonryMcpTools,
|
|
5
5
|
createApiClient
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WGGB7QBD.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-SLCGTOKT.js";
|
|
10
10
|
|
|
11
11
|
// src/mcp/cli.ts
|
|
12
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.124.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",
|
|
@@ -66,26 +66,26 @@
|
|
|
66
66
|
"tsup": "^8.5.1",
|
|
67
67
|
"tsx": "^4.19.0",
|
|
68
68
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
70
69
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
71
|
-
"@ainyc/canonry-
|
|
70
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
72
71
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
72
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
73
73
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
75
74
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
76
75
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
77
|
-
"@ainyc/canonry-integration-google": "0.0.0",
|
|
78
76
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
77
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
79
78
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
80
79
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
81
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
82
80
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
83
|
-
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
84
81
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
85
|
-
"@ainyc/canonry-
|
|
86
|
-
"@ainyc/canonry-provider-
|
|
82
|
+
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
83
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
84
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
87
85
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
88
|
-
"@ainyc/canonry-
|
|
86
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
87
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
88
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|
|
91
91
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|