@canonry/canonry 4.130.0 → 4.131.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-Ydzb2Y_Y.js → AuditHistoryPanel-yJXZMO5t.js} +1 -1
- package/assets/assets/{BacklinksPage-DYodEusK.js → BacklinksPage-6VTLbAYx.js} +1 -1
- package/assets/assets/{ChartPrimitives-D67hsnF7.js → ChartPrimitives-D5YGiDLi.js} +1 -1
- package/assets/assets/{HistoryPage-_h9ITL1w.js → HistoryPage-BxdTM6-R.js} +1 -1
- package/assets/assets/{ProjectPage-fCJKCcHE.js → ProjectPage-BJKxZPRO.js} +1 -1
- package/assets/assets/{RunRow-DzUNyTE-.js → RunRow-DTrAO7tE.js} +1 -1
- package/assets/assets/{RunsPage-FTvAjptk.js → RunsPage-CHU0DQGl.js} +1 -1
- package/assets/assets/{SettingsPage-CvgpYEAt.js → SettingsPage-bOIwju6t.js} +1 -1
- package/assets/assets/{TrafficPage-qaMW9k6o.js → TrafficPage-BKvuR482.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-CRCso7_A.js → TrafficSourceDetailPage-3-iUTgQg.js} +1 -1
- package/assets/assets/{arrow-left-C--lHdP2.js → arrow-left-BXSfGhr6.js} +1 -1
- package/assets/assets/{extract-error-message-DVqYbKpB.js → extract-error-message-DEAY62LS.js} +1 -1
- package/assets/assets/{index-CdXn0JEf.js → index-CfjIYitV.js} +65 -65
- package/assets/assets/{trash-2-CyKRU3tR.js → trash-2-O1wo9IX1.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-NVRJZU6V.js → chunk-3WBAJKRR.js} +4 -0
- package/dist/{chunk-QR5U2K3O.js → chunk-5GQ6FF5R.js} +4 -4
- package/dist/{chunk-WIALMCXM.js → chunk-73HPY6XQ.js} +1 -1
- package/dist/{chunk-5XU6WEMK.js → chunk-ZXVWL5HX.js} +308 -4
- package/dist/cli.js +4 -4
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-53GUE6EI.js → intelligence-service-YJKQQYJQ.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as a}from"./index-
|
|
1
|
+
import{c as a}from"./index-CfjIYitV.js";const c=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],d=a("circle-check",c);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"}]],k=a("circle-question-mark",e);const t=[["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=a("download",t);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],r=a("external-link",o);const n=[["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"}]],y=a("trash-2",n);export{d as C,s as D,r as E,y as T,k 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-CfjIYitV.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">
|
|
@@ -3938,6 +3938,10 @@ var ga4SyncResponseDtoSchema = z25.object({
|
|
|
3938
3938
|
socialReferralCount: z25.number().int().nonnegative(),
|
|
3939
3939
|
days: z25.number().int().nonnegative(),
|
|
3940
3940
|
syncedAt: z25.string(),
|
|
3941
|
+
measurement: z25.object({
|
|
3942
|
+
acquisition: z25.object({ days: z25.number().int().nonnegative(), status: z25.enum(["ready", "error"]), rowCount: z25.number().int().nonnegative(), error: z25.string().optional() }),
|
|
3943
|
+
leads: z25.object({ days: z25.number().int().nonnegative(), status: z25.enum(["ready", "error", "not-configured"]), rowCount: z25.number().int().nonnegative(), attributionScope: z25.enum(["landing-page", "channel"]).optional(), error: z25.string().optional() })
|
|
3944
|
+
}),
|
|
3941
3945
|
/**
|
|
3942
3946
|
* Components that were written this run. Present when `only` is set.
|
|
3943
3947
|
* Always includes `traffic` and `summary` (the share denominator) plus
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-73HPY6XQ.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -118,7 +118,7 @@ import {
|
|
|
118
118
|
siteAuditPages,
|
|
119
119
|
siteAuditSnapshots,
|
|
120
120
|
usageCounters
|
|
121
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-ZXVWL5HX.js";
|
|
122
122
|
import {
|
|
123
123
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
124
124
|
AGENT_PROVIDER_IDS,
|
|
@@ -191,7 +191,7 @@ import {
|
|
|
191
191
|
validationError,
|
|
192
192
|
winnabilityClassLabel,
|
|
193
193
|
withRetry
|
|
194
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-3WBAJKRR.js";
|
|
195
195
|
|
|
196
196
|
// src/telemetry.ts
|
|
197
197
|
import crypto from "crypto";
|
|
@@ -7000,7 +7000,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
7000
7000
|
return result;
|
|
7001
7001
|
}
|
|
7002
7002
|
async function backfillInsightsCommand(project, opts) {
|
|
7003
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
7003
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-YJKQQYJQ.js");
|
|
7004
7004
|
const config = loadConfig();
|
|
7005
7005
|
const db = createClient(config.database);
|
|
7006
7006
|
migrate(db);
|
|
@@ -344,7 +344,7 @@ import {
|
|
|
344
344
|
wordpressSchemaDeployResultDtoSchema,
|
|
345
345
|
wordpressSchemaStatusResultDtoSchema,
|
|
346
346
|
wordpressStatusDtoSchema
|
|
347
|
-
} from "./chunk-
|
|
347
|
+
} from "./chunk-3WBAJKRR.js";
|
|
348
348
|
|
|
349
349
|
// src/intelligence-service.ts
|
|
350
350
|
import { eq as eq42, desc as desc19, asc as asc9, and as and33, ne as ne6, or as or8, inArray as inArray15, gte as gte10, lte as lte6 } from "drizzle-orm";
|
|
@@ -22551,11 +22551,14 @@ var GA4_DIMENSIONS = {
|
|
|
22551
22551
|
firstUserSource: "firstUserSource",
|
|
22552
22552
|
firstUserMedium: "firstUserMedium",
|
|
22553
22553
|
sessionDefaultChannelGrouping: "sessionDefaultChannelGrouping",
|
|
22554
|
-
sessionDefaultChannelGroup: "sessionDefaultChannelGroup"
|
|
22554
|
+
sessionDefaultChannelGroup: "sessionDefaultChannelGroup",
|
|
22555
|
+
hostName: "hostName",
|
|
22556
|
+
eventName: "eventName"
|
|
22555
22557
|
};
|
|
22556
22558
|
var GA4_METRICS = {
|
|
22557
22559
|
sessions: "sessions",
|
|
22558
|
-
totalUsers: "totalUsers"
|
|
22560
|
+
totalUsers: "totalUsers",
|
|
22561
|
+
eventCount: "eventCount"
|
|
22559
22562
|
};
|
|
22560
22563
|
|
|
22561
22564
|
// ../integration-google-analytics/src/types.ts
|
|
@@ -22824,6 +22827,100 @@ async function batchRunReports(accessToken, propertyId, requests) {
|
|
|
22824
22827
|
function formatDate2(d) {
|
|
22825
22828
|
return d.toISOString().slice(0, 10);
|
|
22826
22829
|
}
|
|
22830
|
+
function measurementDateRange(days) {
|
|
22831
|
+
const syncDays = Math.min(Math.max(1, days ?? GA4_DEFAULT_SYNC_DAYS), GA4_MAX_SYNC_DAYS);
|
|
22832
|
+
const endDate = /* @__PURE__ */ new Date();
|
|
22833
|
+
const startDate = /* @__PURE__ */ new Date();
|
|
22834
|
+
startDate.setUTCDate(startDate.getUTCDate() - syncDays);
|
|
22835
|
+
return { syncDays, dateRange: { startDate: formatDate2(startDate), endDate: formatDate2(endDate) } };
|
|
22836
|
+
}
|
|
22837
|
+
async function fetchPagedReport(accessToken, propertyId, baseRequest, pageSize = 1e4) {
|
|
22838
|
+
const rows = [];
|
|
22839
|
+
let offset = 0;
|
|
22840
|
+
for (let page = 0; page < GA4_MAX_PAGES; page++) {
|
|
22841
|
+
const response = await runReport(accessToken, propertyId, { ...baseRequest, limit: pageSize, offset });
|
|
22842
|
+
const pageRows = response.rows ?? [];
|
|
22843
|
+
rows.push(...pageRows);
|
|
22844
|
+
offset += pageRows.length;
|
|
22845
|
+
if (pageRows.length < pageSize || response.rowCount !== void 0 && offset >= response.rowCount) break;
|
|
22846
|
+
if (page === GA4_MAX_PAGES - 1) {
|
|
22847
|
+
throw new Error(`GA4 report truncated: page limit (${GA4_MAX_PAGES}) reached before all rows were fetched`);
|
|
22848
|
+
}
|
|
22849
|
+
}
|
|
22850
|
+
return rows;
|
|
22851
|
+
}
|
|
22852
|
+
async function fetchAcquisitionByChannel(accessToken, propertyId, days, options) {
|
|
22853
|
+
validateAccessToken2(accessToken);
|
|
22854
|
+
validatePropertyId(propertyId);
|
|
22855
|
+
const { syncDays, dateRange } = measurementDateRange(days);
|
|
22856
|
+
const rows = await fetchPagedReport(accessToken, propertyId, {
|
|
22857
|
+
dateRanges: [dateRange],
|
|
22858
|
+
dimensions: [
|
|
22859
|
+
{ name: GA4_DIMENSIONS.date },
|
|
22860
|
+
{ name: GA4_DIMENSIONS.sessionDefaultChannelGroup },
|
|
22861
|
+
{ name: GA4_DIMENSIONS.sessionSource },
|
|
22862
|
+
{ name: GA4_DIMENSIONS.sessionMedium },
|
|
22863
|
+
{ name: GA4_DIMENSIONS.hostName },
|
|
22864
|
+
{ name: GA4_DIMENSIONS.landingPagePlusQueryString }
|
|
22865
|
+
],
|
|
22866
|
+
metrics: [{ name: GA4_METRICS.sessions }]
|
|
22867
|
+
}, options?.pageSize);
|
|
22868
|
+
ga4Log("info", "fetch-acquisition.done", { propertyId, days: syncDays, rowCount: rows.length });
|
|
22869
|
+
return { ...dateRange, rows: rows.map((row) => ({
|
|
22870
|
+
date: compactDateToIso(row.dimensionValues[0]?.value ?? ""),
|
|
22871
|
+
channelGroup: row.dimensionValues[1]?.value ?? "(not set)",
|
|
22872
|
+
source: row.dimensionValues[2]?.value ?? "(not set)",
|
|
22873
|
+
medium: row.dimensionValues[3]?.value ?? "(not set)",
|
|
22874
|
+
hostName: row.dimensionValues[4]?.value ?? "(not set)",
|
|
22875
|
+
landingPage: row.dimensionValues[5]?.value ?? "(not set)",
|
|
22876
|
+
sessions: parseInt(row.metricValues[0]?.value ?? "0", 10) || 0
|
|
22877
|
+
})) };
|
|
22878
|
+
}
|
|
22879
|
+
function isLandingPageDimensionIncompatibility(error) {
|
|
22880
|
+
return error instanceof GA4ApiError && error.status === 400 && /landingPagePlusQueryString/i.test(error.message) && /incompatib/i.test(error.message);
|
|
22881
|
+
}
|
|
22882
|
+
async function fetchLeadEvents(accessToken, propertyId, eventNames, days) {
|
|
22883
|
+
validateAccessToken2(accessToken);
|
|
22884
|
+
validatePropertyId(propertyId);
|
|
22885
|
+
const { dateRange } = measurementDateRange(days);
|
|
22886
|
+
const filter = { orGroup: { expressions: eventNames.map((value) => ({ filter: {
|
|
22887
|
+
fieldName: GA4_DIMENSIONS.eventName,
|
|
22888
|
+
stringFilter: { matchType: "EXACT", value }
|
|
22889
|
+
} })) } };
|
|
22890
|
+
const dimensions = [
|
|
22891
|
+
{ name: GA4_DIMENSIONS.date },
|
|
22892
|
+
{ name: GA4_DIMENSIONS.eventName },
|
|
22893
|
+
{ name: GA4_DIMENSIONS.sessionDefaultChannelGroup },
|
|
22894
|
+
{ name: GA4_DIMENSIONS.sessionSource },
|
|
22895
|
+
{ name: GA4_DIMENSIONS.sessionMedium }
|
|
22896
|
+
];
|
|
22897
|
+
const request = (landingPage) => ({
|
|
22898
|
+
dateRanges: [dateRange],
|
|
22899
|
+
dimensions: landingPage ? [...dimensions, { name: GA4_DIMENSIONS.hostName }, { name: GA4_DIMENSIONS.landingPagePlusQueryString }] : dimensions,
|
|
22900
|
+
metrics: [{ name: GA4_METRICS.eventCount }],
|
|
22901
|
+
dimensionFilter: filter
|
|
22902
|
+
});
|
|
22903
|
+
let attributionScope = "landing-page";
|
|
22904
|
+
let rawRows;
|
|
22905
|
+
try {
|
|
22906
|
+
rawRows = await fetchPagedReport(accessToken, propertyId, request(true));
|
|
22907
|
+
} catch (error) {
|
|
22908
|
+
if (!isLandingPageDimensionIncompatibility(error)) throw error;
|
|
22909
|
+
attributionScope = "channel";
|
|
22910
|
+
rawRows = await fetchPagedReport(accessToken, propertyId, request(false));
|
|
22911
|
+
}
|
|
22912
|
+
const rows = rawRows.map((row) => ({
|
|
22913
|
+
date: compactDateToIso(row.dimensionValues[0]?.value ?? ""),
|
|
22914
|
+
eventName: row.dimensionValues[1]?.value ?? "(not set)",
|
|
22915
|
+
channelGroup: row.dimensionValues[2]?.value ?? "(not set)",
|
|
22916
|
+
source: row.dimensionValues[3]?.value ?? "(not set)",
|
|
22917
|
+
medium: row.dimensionValues[4]?.value ?? "(not set)",
|
|
22918
|
+
hostName: attributionScope === "landing-page" ? row.dimensionValues[5]?.value ?? "(not available)" : "(not available)",
|
|
22919
|
+
landingPage: attributionScope === "landing-page" ? row.dimensionValues[6]?.value ?? "(not available)" : "(not available)",
|
|
22920
|
+
eventCount: parseInt(row.metricValues[0]?.value ?? "0", 10) || 0
|
|
22921
|
+
}));
|
|
22922
|
+
return { ...dateRange, attributionScope, rows };
|
|
22923
|
+
}
|
|
22827
22924
|
var AI_REFERRAL_SOURCE_FILTERS = [
|
|
22828
22925
|
{ matchType: "CONTAINS", value: "perplexity" },
|
|
22829
22926
|
{ matchType: "CONTAINS", value: "gemini" },
|
|
@@ -30050,6 +30147,134 @@ function normalizeAiTrafficClass(value) {
|
|
|
30050
30147
|
function emptyAiCounts() {
|
|
30051
30148
|
return { sessions: 0, users: 0 };
|
|
30052
30149
|
}
|
|
30150
|
+
function persistAcquisitionMeasurement(db, input) {
|
|
30151
|
+
const { startDate, endDate } = input.report;
|
|
30152
|
+
db.transaction((tx) => {
|
|
30153
|
+
tx.delete(gaAcquisitionDaily).where(and23(
|
|
30154
|
+
eq29(gaAcquisitionDaily.projectId, input.projectId),
|
|
30155
|
+
sql13`${gaAcquisitionDaily.date} >= ${startDate}`,
|
|
30156
|
+
sql13`${gaAcquisitionDaily.date} <= ${endDate}`
|
|
30157
|
+
)).run();
|
|
30158
|
+
for (const row of input.report.rows) {
|
|
30159
|
+
tx.insert(gaAcquisitionDaily).values({
|
|
30160
|
+
id: crypto24.randomUUID(),
|
|
30161
|
+
projectId: input.projectId,
|
|
30162
|
+
date: row.date,
|
|
30163
|
+
channelGroup: row.channelGroup,
|
|
30164
|
+
source: row.source,
|
|
30165
|
+
medium: row.medium,
|
|
30166
|
+
hostName: row.hostName,
|
|
30167
|
+
landingPage: row.landingPage,
|
|
30168
|
+
landingPageNormalized: normalizeUrlPath(row.landingPage),
|
|
30169
|
+
sessions: row.sessions,
|
|
30170
|
+
syncedAt: input.syncedAt,
|
|
30171
|
+
syncRunId: input.runId,
|
|
30172
|
+
createdAt: input.syncedAt
|
|
30173
|
+
}).run();
|
|
30174
|
+
}
|
|
30175
|
+
tx.insert(gaMeasurementSyncStates).values({
|
|
30176
|
+
projectId: input.projectId,
|
|
30177
|
+
acquisitionStatus: "ready",
|
|
30178
|
+
acquisitionError: null,
|
|
30179
|
+
acquisitionSyncedAt: input.syncedAt,
|
|
30180
|
+
updatedAt: input.syncedAt
|
|
30181
|
+
}).onConflictDoUpdate({
|
|
30182
|
+
target: gaMeasurementSyncStates.projectId,
|
|
30183
|
+
set: {
|
|
30184
|
+
acquisitionStatus: "ready",
|
|
30185
|
+
acquisitionError: null,
|
|
30186
|
+
acquisitionSyncedAt: input.syncedAt,
|
|
30187
|
+
updatedAt: input.syncedAt
|
|
30188
|
+
}
|
|
30189
|
+
}).run();
|
|
30190
|
+
});
|
|
30191
|
+
}
|
|
30192
|
+
function persistLeadMeasurement(db, input) {
|
|
30193
|
+
const { startDate, endDate } = input.report;
|
|
30194
|
+
db.transaction((tx) => {
|
|
30195
|
+
tx.delete(gaLeadEventsDaily).where(and23(
|
|
30196
|
+
eq29(gaLeadEventsDaily.projectId, input.projectId),
|
|
30197
|
+
sql13`${gaLeadEventsDaily.date} >= ${startDate}`,
|
|
30198
|
+
sql13`${gaLeadEventsDaily.date} <= ${endDate}`
|
|
30199
|
+
)).run();
|
|
30200
|
+
for (const row of input.report.rows) {
|
|
30201
|
+
tx.insert(gaLeadEventsDaily).values({
|
|
30202
|
+
id: crypto24.randomUUID(),
|
|
30203
|
+
projectId: input.projectId,
|
|
30204
|
+
date: row.date,
|
|
30205
|
+
eventName: row.eventName,
|
|
30206
|
+
channelGroup: row.channelGroup,
|
|
30207
|
+
source: row.source,
|
|
30208
|
+
medium: row.medium,
|
|
30209
|
+
hostName: row.hostName,
|
|
30210
|
+
landingPage: row.landingPage,
|
|
30211
|
+
landingPageNormalized: input.report.attributionScope === "landing-page" ? normalizeUrlPath(row.landingPage) : null,
|
|
30212
|
+
attributionScope: input.report.attributionScope,
|
|
30213
|
+
eventCount: row.eventCount,
|
|
30214
|
+
syncedAt: input.syncedAt,
|
|
30215
|
+
syncRunId: input.runId,
|
|
30216
|
+
createdAt: input.syncedAt
|
|
30217
|
+
}).run();
|
|
30218
|
+
}
|
|
30219
|
+
tx.insert(gaMeasurementSyncStates).values({
|
|
30220
|
+
projectId: input.projectId,
|
|
30221
|
+
leadStatus: "ready",
|
|
30222
|
+
leadError: null,
|
|
30223
|
+
leadSyncedAt: input.syncedAt,
|
|
30224
|
+
leadAttributionScope: input.report.attributionScope,
|
|
30225
|
+
updatedAt: input.syncedAt
|
|
30226
|
+
}).onConflictDoUpdate({
|
|
30227
|
+
target: gaMeasurementSyncStates.projectId,
|
|
30228
|
+
set: {
|
|
30229
|
+
leadStatus: "ready",
|
|
30230
|
+
leadError: null,
|
|
30231
|
+
leadSyncedAt: input.syncedAt,
|
|
30232
|
+
leadAttributionScope: input.report.attributionScope,
|
|
30233
|
+
updatedAt: input.syncedAt
|
|
30234
|
+
}
|
|
30235
|
+
}).run();
|
|
30236
|
+
});
|
|
30237
|
+
}
|
|
30238
|
+
function resetLeadMeasurement(db, projectId, updatedAt) {
|
|
30239
|
+
db.transaction((tx) => {
|
|
30240
|
+
tx.delete(gaLeadEventsDaily).where(eq29(gaLeadEventsDaily.projectId, projectId)).run();
|
|
30241
|
+
tx.insert(gaMeasurementSyncStates).values({ projectId, leadStatus: "never-synced", leadError: null, leadSyncedAt: null, leadAttributionScope: null, updatedAt }).onConflictDoUpdate({
|
|
30242
|
+
target: gaMeasurementSyncStates.projectId,
|
|
30243
|
+
set: { leadStatus: "never-synced", leadError: null, leadSyncedAt: null, leadAttributionScope: null, updatedAt }
|
|
30244
|
+
}).run();
|
|
30245
|
+
});
|
|
30246
|
+
}
|
|
30247
|
+
function persistMeasurementError(db, projectId, component, message, updatedAt) {
|
|
30248
|
+
if (component === "acquisition") {
|
|
30249
|
+
db.insert(gaMeasurementSyncStates).values({
|
|
30250
|
+
projectId,
|
|
30251
|
+
acquisitionStatus: "error",
|
|
30252
|
+
acquisitionError: message,
|
|
30253
|
+
updatedAt
|
|
30254
|
+
}).onConflictDoUpdate({
|
|
30255
|
+
target: gaMeasurementSyncStates.projectId,
|
|
30256
|
+
set: {
|
|
30257
|
+
acquisitionStatus: "error",
|
|
30258
|
+
acquisitionError: message,
|
|
30259
|
+
updatedAt
|
|
30260
|
+
}
|
|
30261
|
+
}).run();
|
|
30262
|
+
return;
|
|
30263
|
+
}
|
|
30264
|
+
db.insert(gaMeasurementSyncStates).values({
|
|
30265
|
+
projectId,
|
|
30266
|
+
leadStatus: "error",
|
|
30267
|
+
leadError: message,
|
|
30268
|
+
updatedAt
|
|
30269
|
+
}).onConflictDoUpdate({
|
|
30270
|
+
target: gaMeasurementSyncStates.projectId,
|
|
30271
|
+
set: {
|
|
30272
|
+
leadStatus: "error",
|
|
30273
|
+
leadError: message,
|
|
30274
|
+
updatedAt
|
|
30275
|
+
}
|
|
30276
|
+
}).run();
|
|
30277
|
+
}
|
|
30053
30278
|
function summarizeAiReferralCounts(rows) {
|
|
30054
30279
|
const dedupeGroups = /* @__PURE__ */ new Map();
|
|
30055
30280
|
const bySessionChannelGroup = /* @__PURE__ */ new Map();
|
|
@@ -30313,6 +30538,10 @@ async function ga4Routes(app, opts) {
|
|
|
30313
30538
|
const syncSummary = true;
|
|
30314
30539
|
const syncAi = !only || only === "ai";
|
|
30315
30540
|
const syncSocial = !only || only === "social";
|
|
30541
|
+
const measurementState = app.db.select().from(gaMeasurementSyncStates).where(eq29(gaMeasurementSyncStates.projectId, project.id)).get();
|
|
30542
|
+
const acquisitionDays = measurementState?.acquisitionSyncedAt != null ? Math.min(Math.max(1, days), 90) : 90;
|
|
30543
|
+
const leadDays = measurementState?.leadSyncedAt != null ? Math.min(Math.max(1, days), 90) : 90;
|
|
30544
|
+
const leadEventNames = project.measurement.leadEventNames;
|
|
30316
30545
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
30317
30546
|
const runId = crypto24.randomUUID();
|
|
30318
30547
|
app.db.insert(runs).values({
|
|
@@ -30338,6 +30567,10 @@ async function ga4Routes(app, opts) {
|
|
|
30338
30567
|
if (syncTraffic) fetches.push(fetchTrafficByLandingPage(accessToken, propertyId, days));
|
|
30339
30568
|
if (syncAi) fetches.push(fetchAiReferrals(accessToken, propertyId, days));
|
|
30340
30569
|
if (syncSocial) fetches.push(fetchSocialReferrals(accessToken, propertyId, days));
|
|
30570
|
+
const measurementFetch = Promise.allSettled([
|
|
30571
|
+
fetchAcquisitionByChannel(accessToken, propertyId, acquisitionDays),
|
|
30572
|
+
leadEventNames.length > 0 ? fetchLeadEvents(accessToken, propertyId, leadEventNames, leadDays) : Promise.resolve(null)
|
|
30573
|
+
]);
|
|
30341
30574
|
const results = await Promise.all(fetches);
|
|
30342
30575
|
const summary = results[0];
|
|
30343
30576
|
const windowSummaries = results.slice(1, 1 + WINDOW_KEYS.length);
|
|
@@ -30483,7 +30716,74 @@ async function ga4Routes(app, opts) {
|
|
|
30483
30716
|
}
|
|
30484
30717
|
}
|
|
30485
30718
|
});
|
|
30486
|
-
|
|
30719
|
+
const [acquisitionSettled, leadsSettled] = await measurementFetch;
|
|
30720
|
+
const measurementNow = (/* @__PURE__ */ new Date()).toISOString();
|
|
30721
|
+
const recordMeasurementFailure = (component, reason) => {
|
|
30722
|
+
const message = reason instanceof Error ? reason.message : String(reason);
|
|
30723
|
+
gaLog("warn", "measurement.component-failed", {
|
|
30724
|
+
projectId: project.id,
|
|
30725
|
+
runId,
|
|
30726
|
+
component,
|
|
30727
|
+
error: message
|
|
30728
|
+
});
|
|
30729
|
+
try {
|
|
30730
|
+
persistMeasurementError(app.db, project.id, component, message, measurementNow);
|
|
30731
|
+
} catch (stateError) {
|
|
30732
|
+
gaLog("error", "measurement.state-write-failed", {
|
|
30733
|
+
projectId: project.id,
|
|
30734
|
+
runId,
|
|
30735
|
+
component,
|
|
30736
|
+
error: stateError instanceof Error ? stateError.message : String(stateError)
|
|
30737
|
+
});
|
|
30738
|
+
}
|
|
30739
|
+
return { status: "error", days: component === "acquisition" ? acquisitionDays : leadDays, rowCount: 0, error: message };
|
|
30740
|
+
};
|
|
30741
|
+
const acquisitionResult = (() => {
|
|
30742
|
+
if (acquisitionSettled.status === "rejected") {
|
|
30743
|
+
return recordMeasurementFailure("acquisition", acquisitionSettled.reason);
|
|
30744
|
+
}
|
|
30745
|
+
try {
|
|
30746
|
+
persistAcquisitionMeasurement(app.db, {
|
|
30747
|
+
projectId: project.id,
|
|
30748
|
+
runId,
|
|
30749
|
+
syncedAt: measurementNow,
|
|
30750
|
+
report: acquisitionSettled.value
|
|
30751
|
+
});
|
|
30752
|
+
return {
|
|
30753
|
+
status: "ready",
|
|
30754
|
+
days: acquisitionDays,
|
|
30755
|
+
rowCount: acquisitionSettled.value.rows.length
|
|
30756
|
+
};
|
|
30757
|
+
} catch (error) {
|
|
30758
|
+
return recordMeasurementFailure("acquisition", error);
|
|
30759
|
+
}
|
|
30760
|
+
})();
|
|
30761
|
+
const leadResult = (() => {
|
|
30762
|
+
if (leadsSettled.status === "rejected") {
|
|
30763
|
+
return recordMeasurementFailure("leads", leadsSettled.reason);
|
|
30764
|
+
}
|
|
30765
|
+
if (leadsSettled.value === null) {
|
|
30766
|
+
resetLeadMeasurement(app.db, project.id, measurementNow);
|
|
30767
|
+
return { status: "not-configured", days: 0, rowCount: 0 };
|
|
30768
|
+
}
|
|
30769
|
+
try {
|
|
30770
|
+
persistLeadMeasurement(app.db, {
|
|
30771
|
+
projectId: project.id,
|
|
30772
|
+
runId,
|
|
30773
|
+
syncedAt: measurementNow,
|
|
30774
|
+
report: leadsSettled.value
|
|
30775
|
+
});
|
|
30776
|
+
return {
|
|
30777
|
+
status: "ready",
|
|
30778
|
+
days: leadDays,
|
|
30779
|
+
rowCount: leadsSettled.value.rows.length,
|
|
30780
|
+
attributionScope: leadsSettled.value.attributionScope
|
|
30781
|
+
};
|
|
30782
|
+
} catch (error) {
|
|
30783
|
+
return recordMeasurementFailure("leads", error);
|
|
30784
|
+
}
|
|
30785
|
+
})();
|
|
30786
|
+
app.db.update(runs).set({ status: RunStatuses.completed, finishedAt: measurementNow }).where(eq29(runs.id, runId)).run();
|
|
30487
30787
|
const syncedComponents = only ? [
|
|
30488
30788
|
...syncTraffic ? ["traffic"] : [],
|
|
30489
30789
|
...syncSummary ? ["summary"] : [],
|
|
@@ -30507,6 +30807,10 @@ async function ga4Routes(app, opts) {
|
|
|
30507
30807
|
socialReferralCount: socialReferrals.length,
|
|
30508
30808
|
days,
|
|
30509
30809
|
syncedAt: now,
|
|
30810
|
+
measurement: {
|
|
30811
|
+
acquisition: acquisitionResult,
|
|
30812
|
+
leads: leadResult
|
|
30813
|
+
},
|
|
30510
30814
|
...syncedComponents ? { syncedComponents } : {}
|
|
30511
30815
|
};
|
|
30512
30816
|
} catch (e) {
|
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-5GQ6FF5R.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-73HPY6XQ.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-ZXVWL5HX.js";
|
|
58
58
|
import {
|
|
59
59
|
AdsOperationKinds,
|
|
60
60
|
AdsOperationStates,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
providerQuotaPolicySchema,
|
|
98
98
|
resolveProviderInput,
|
|
99
99
|
winnabilityClassSchema
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-3WBAJKRR.js";
|
|
101
101
|
|
|
102
102
|
// src/cli.ts
|
|
103
103
|
import { pathToFileURL } from "url";
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5GQ6FF5R.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-73HPY6XQ.js";
|
|
7
|
+
import "./chunk-ZXVWL5HX.js";
|
|
8
|
+
import "./chunk-3WBAJKRR.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-73HPY6XQ.js";
|
|
7
7
|
import {
|
|
8
8
|
isReadOnlyKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-3WBAJKRR.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.131.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",
|
|
@@ -67,25 +67,25 @@
|
|
|
67
67
|
"tsx": "^4.19.0",
|
|
68
68
|
"@ainyc/canonry-api-client": "0.0.0",
|
|
69
69
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
70
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
70
71
|
"@ainyc/canonry-config": "0.0.0",
|
|
71
72
|
"@ainyc/canonry-db": "0.0.0",
|
|
72
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
73
73
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
74
|
-
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
75
|
-
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
76
74
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
75
|
+
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
77
76
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
78
77
|
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
79
78
|
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
80
|
-
"@ainyc/canonry-integration-
|
|
79
|
+
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
80
|
+
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
81
81
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
82
|
-
"@ainyc/canonry-
|
|
82
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
83
83
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
84
84
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
85
|
-
"@ainyc/canonry-
|
|
85
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
86
86
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
87
|
-
"@ainyc/canonry-provider-
|
|
88
|
-
"@ainyc/canonry-provider-
|
|
87
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
88
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
89
89
|
},
|
|
90
90
|
"scripts": {
|
|
91
91
|
"build": "tsx scripts/copy-agent-assets.ts && tsup && tsx build-web.ts",
|