@canonry/canonry 7.92.1 → 7.94.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/agent-workspace/skills/aero/references/ai-traffic-tracking.md +7 -1
- package/assets/agent-workspace/skills/canonry/references/ai-traffic-tracking.md +7 -1
- package/assets/agent-workspace/skills/canonry/references/server-side-traffic.md +2 -0
- package/assets/assets/{AgentSetupPage-Dr5ZoPYi.js → AgentSetupPage-BlPXN_oH.js} +1 -1
- package/assets/assets/{AuditHistoryPanel-Dc8pGeZT.js → AuditHistoryPanel-N8Z4gng7.js} +1 -1
- package/assets/assets/{BacklinksPage-zEaP7G6s.js → BacklinksPage-DSrgqlkj.js} +1 -1
- package/assets/assets/{HistoryPage-9OaxBSY8.js → HistoryPage-v2jbUkle.js} +1 -1
- package/assets/assets/{MeasurementPropertyPage-k_mqkoWn.js → MeasurementPropertyPage-C1eIWJPD.js} +1 -1
- package/assets/assets/{ProjectPage-vgHaFT7S.js → ProjectPage-Ho61hE8f.js} +7 -7
- package/assets/assets/{RunsPage-CXkefezd.js → RunsPage-CXZJDdnr.js} +1 -1
- package/assets/assets/{SettingsPage-C8FUNUN5.js → SettingsPage-CeLvWs_T.js} +1 -1
- package/assets/assets/{SiteHealthSection-C94uYTE3.js → SiteHealthSection-C2Ys7rzL.js} +2 -2
- package/assets/assets/{ToneBadge-COrS2zpP.js → ToneBadge-C49669Ol.js} +1 -1
- package/assets/assets/{TrafficPage-KlGx3-bc.js → TrafficPage-CEsmS5N1.js} +1 -1
- package/assets/assets/TrafficSourceDetailPage-D31g1FXV.js +1 -0
- package/assets/assets/{account-context-F2VRKRtu.js → account-context-CGIyok0O.js} +1 -1
- package/assets/assets/{agent-trust-copy-Hb775a57.js → agent-trust-copy-B-3akxrd.js} +1 -1
- package/assets/assets/{card-P1VA-JnV.js → card-BMjN_ofC.js} +1 -1
- package/assets/assets/{format-helpers-COfTmLRL.js → format-helpers-Blu0QNcd.js} +1 -1
- package/assets/assets/{index-DHrWeA6k.js → index-B-t8djQ-.js} +4 -4
- package/assets/assets/index-DsdpvA7m.css +1 -0
- package/assets/assets/{query-client-BHtq57Sw.js → query-client-DdwTc28X.js} +1 -1
- package/assets/assets/{react-query-IhpEAOba.js → react-query-dnbkXy7A.js} +1 -1
- package/assets/assets/{react-sigma_core.esm.min-B4NX5_aX.js → react-sigma_core.esm.min-5sP0Pb_F.js} +1 -1
- package/assets/assets/server-traffic-403Q1CKm.js +1 -0
- package/assets/assets/{service-m9l8my0x.js → service-ChEbo8oM.js} +1 -1
- package/assets/index.html +8 -8
- package/dist/{ads-LRHVFP2J.js → ads-6RVS23I5.js} +3 -3
- package/dist/{agent-P7HWL7VX.js → agent-N5LH7QNA.js} +7 -7
- package/dist/{agent-ask-S374MIJS.js → agent-ask-IJV2PWPN.js} +3 -3
- package/dist/{agent-conversations-3SSKVUYG.js → agent-conversations-STISIDWB.js} +3 -3
- package/dist/{agent-journeys-ZEO7Z4QR.js → agent-journeys-VCP5MD2W.js} +3 -3
- package/dist/{agent-memory-E5YVW5WY.js → agent-memory-XQQNXRY6.js} +3 -3
- package/dist/{agent-providers-BWWB42XJ.js → agent-providers-IW2Q6WPP.js} +3 -3
- package/dist/{agent-transcript-YG7TTHWS.js → agent-transcript-5XUCHOOT.js} +3 -3
- package/dist/{analytics-AIKX4BUM.js → analytics-RZZZBC4H.js} +3 -3
- package/dist/{apply-5MPSMIKM.js → apply-X5ZTHGSJ.js} +3 -3
- package/dist/{backfill-2BFEE6XJ.js → backfill-ZF6RX27O.js} +10 -10
- package/dist/{backlinks-L6BYIJIK.js → backlinks-WZ7YUKHH.js} +3 -3
- package/dist/{bing-E4ZSEVQV.js → bing-Z4A5NHOC.js} +3 -3
- package/dist/{bootstrap-V7OE6XXB.js → bootstrap-OCJ7EIXK.js} +10 -10
- package/dist/{cdp-LWNX6UZF.js → cdp-YGZFLTFT.js} +7 -7
- package/dist/{chunk-EWZOL56J.js → chunk-32N7BGTD.js} +3 -3
- package/dist/{chunk-KKSE52CI.js → chunk-3D4VEWDJ.js} +6 -6
- package/dist/{chunk-TY5YTNLU.js → chunk-55EFIQP7.js} +2 -2
- package/dist/{chunk-GNHXSSQM.js → chunk-7JQM46YO.js} +2 -2
- package/dist/{chunk-3WWSOWXP.js → chunk-B5JKQXRN.js} +2 -2
- package/dist/{chunk-ZTRGUTUP.js → chunk-BJAOD3NW.js} +5 -5
- package/dist/{chunk-H3PWMM4K.js → chunk-BL4CZJYJ.js} +32 -1
- package/dist/{chunk-K7ZG6K7J.js → chunk-CBNDEKI6.js} +1 -1
- package/dist/{chunk-N2EWSWZD.js → chunk-D6KTO5TO.js} +1 -1
- package/dist/{chunk-P6ZDIVFZ.js → chunk-ECUJEKIO.js} +1 -1
- package/dist/{chunk-IDISBRPO.js → chunk-FM74QGW5.js} +7 -7
- package/dist/{chunk-ZPVJ5PVB.js → chunk-IUDXV6PH.js} +2 -2
- package/dist/{chunk-DEFHTBJV.js → chunk-JDOAULVX.js} +1 -1
- package/dist/{chunk-BYDJIBAB.js → chunk-K2JCPF2W.js} +358 -358
- package/dist/{chunk-U3T37P7H.js → chunk-K63XX7VY.js} +3 -3
- package/dist/{chunk-2D3JYWFX.js → chunk-LDY66O7A.js} +4 -4
- package/dist/{chunk-T5DH6FEH.js → chunk-LXJAXAJD.js} +1 -1
- package/dist/{chunk-76KBMLPR.js → chunk-M6DYUCNB.js} +1 -1
- package/dist/{chunk-BRNZ3G3B.js → chunk-N6MXZ5SC.js} +35 -22
- package/dist/{chunk-ZEZPTUUB.js → chunk-N7PGV6QQ.js} +2709 -2530
- package/dist/{chunk-FYYOX7UY.js → chunk-NSUB2S4V.js} +666 -623
- package/dist/{chunk-ERSHLW5J.js → chunk-NUBADAA4.js} +4 -4
- package/dist/{chunk-MDYFHX5Y.js → chunk-PR5FCYNN.js} +21 -21
- package/dist/{chunk-7534NXSP.js → chunk-QDGW75MP.js} +2 -1
- package/dist/{chunk-AUC47DFW.js → chunk-R7BX2ZSQ.js} +1 -1
- package/dist/{chunk-BTYOU24P.js → chunk-RJLSGCOI.js} +2 -2
- package/dist/{chunk-WONUYAKB.js → chunk-RSBIHKHH.js} +4 -4
- package/dist/{chunk-O7D7KV75.js → chunk-S6KJYLOV.js} +3 -3
- package/dist/{chunk-4HLR3DRQ.js → chunk-SFNSSHIN.js} +1 -1
- package/dist/{chunk-CIP3CE2C.js → chunk-UPBQHUE6.js} +3 -3
- package/dist/{chunk-XYQMPYWE.js → chunk-VGAQH7KI.js} +1 -1
- package/dist/{chunk-UMTYAPCQ.js → chunk-XIHIB7VP.js} +6 -5
- package/dist/{chunk-ZTCQVHQV.js → chunk-XPBEDIXW.js} +2 -2
- package/dist/{chunk-4QYGB5IC.js → chunk-YGHI3W4D.js} +1 -1
- package/dist/{chunk-JZVTSC2V.js → chunk-YRCKRY3Q.js} +2 -2
- package/dist/{citations-BYSB6NON.js → citations-IUITVPHO.js} +3 -3
- package/dist/{cli-catalog-CFCLMVSK.js → cli-catalog-IAPKU2RG.js} +3 -3
- package/dist/{cli-commands-G5LDZRUU.js → cli-commands-FICINBUR.js} +7 -7
- package/dist/cli.js +13 -13
- package/dist/{competitor-DUYU7EL7.js → competitor-U5DMMCIA.js} +3 -3
- package/dist/{content-OGURKOCE.js → content-ZQIZUNF5.js} +3 -3
- package/dist/{dashboard-UOIHD75S.js → dashboard-KPGX4EQT.js} +6 -6
- package/dist/{demo-UTXZOVOZ.js → demo-NEWVCEXD.js} +1 -1
- package/dist/{demo-server-4TRTOGKP.js → demo-server-5GJEGG5K.js} +12 -12
- package/dist/{discover-SHUCBUDJ.js → discover-HSPVFHKK.js} +3 -3
- package/dist/{discover-eval-3ZTYLTGU.js → discover-eval-BYKPJ3DL.js} +3 -3
- package/dist/{doctor-FRSV5GAR.js → doctor-CK4BTTWH.js} +3 -3
- package/dist/{evidence-7UJHNILW.js → evidence-BX3CWPCT.js} +3 -3
- package/dist/{export-cmd-2DAWSD52.js → export-cmd-QMCRDMPZ.js} +3 -3
- package/dist/{ga-K2EVI3KO.js → ga-RMTUMSEJ.js} +3 -3
- package/dist/{gbp-NXFINC7N.js → gbp-JK67SYLW.js} +3 -3
- package/dist/{google-J4T52EIG.js → google-PJSK6IJV.js} +4 -4
- package/dist/{google-marketing-PZGKZPEB.js → google-marketing-UQ2FONXU.js} +1 -1
- package/dist/{health-cmd-5IHX5GRQ.js → health-cmd-ZDXFD53P.js} +3 -3
- package/dist/{history-IVO5IVH2.js → history-OYL7SPEY.js} +3 -3
- package/dist/index.d.ts +42 -23
- package/dist/index.js +25 -25
- package/dist/{init-TNCLNDMS.js → init-DZUNAQBN.js} +12 -12
- package/dist/{insights-SPA2BVMV.js → insights-AIBLDPX6.js} +3 -3
- package/dist/intelligence-service-YLNZTJQA.js +16 -0
- package/dist/{journeys-7FAHZRGP.js → journeys-EDEET2EC.js} +3 -3
- package/dist/{keys-PPBHRYPZ.js → keys-SEZQTYGJ.js} +3 -3
- package/dist/{keyword-C4ULYIWF.js → keyword-6FJIWTHW.js} +3 -3
- package/dist/{logs-X7NQN4UT.js → logs-EML2KKOP.js} +3 -3
- package/dist/{mcp-ERMFW6WJ.js → mcp-AA5QUNBZ.js} +4 -4
- package/dist/mcp.js +9 -9
- package/dist/{measurement-plan-7IPWYNIC.js → measurement-plan-ALHRGRPH.js} +5 -5
- package/dist/{notify-AC4ZHLUK.js → notify-EVTI3SWQ.js} +3 -3
- package/dist/{organic-evidence-GDDMNJHN.js → organic-evidence-EXQQ6R7H.js} +3 -3
- package/dist/{overview-7VCUIYQE.js → overview-5CIFLSDG.js} +4 -4
- package/dist/{project-N4RGX5CT.js → project-DNDENHRU.js} +3 -3
- package/dist/{query-Y7LGD6PG.js → query-ETMHFVKZ.js} +3 -3
- package/dist/{research-WTZO3D7B.js → research-Q5X46CR5.js} +3 -3
- package/dist/{results-export-BYUFBWEK.js → results-export-DZZANVYY.js} +3 -3
- package/dist/{run-SXMD6GW5.js → run-OQJXRJ42.js} +4 -4
- package/dist/{schedule-UQFPQBHI.js → schedule-6AI3J2AB.js} +3 -3
- package/dist/{search-EJUJRZEE.js → search-7TAJBSHE.js} +3 -3
- package/dist/{serve-ON5OOCRY.js → serve-WD44V3TK.js} +26 -26
- package/dist/{session-4RJTRXIO.js → session-LTKCS763.js} +13 -13
- package/dist/{settings-ZBP3KDJK.js → settings-EUMYGNIV.js} +3 -3
- package/dist/{sitemaps-KVROUSLB.js → sitemaps-I4QPLAZW.js} +3 -3
- package/dist/{skills-AGAHFQD5.js → skills-PTYYU3FR.js} +2 -2
- package/dist/{snapshot-WDK6ZSJA.js → snapshot-62FF4GEA.js} +3 -3
- package/dist/{src-XGUBO65J.js → src-LRYXRHLW.js} +2 -2
- package/dist/{status-IFUJIB73.js → status-VRWPYTY3.js} +4 -4
- package/dist/{technical-aeo-6KR3YH4X.js → technical-aeo-OKZW2GAX.js} +3 -3
- package/dist/{telemetry-EZNMZMH6.js → telemetry-RRTHKD6W.js} +4 -4
- package/dist/{tools-HRHCCGJ5.js → tools-F7WCCKZW.js} +11 -11
- package/dist/{traffic-7OSHD23C.js → traffic-H6RDZWGG.js} +13 -8
- package/dist/{trends-I3NWFNHX.js → trends-RZOQW2LE.js} +3 -3
- package/dist/{users-VBLZGMML.js → users-KFBCBA3V.js} +3 -3
- package/dist/{visibility-stats-6YAV2MTM.js → visibility-stats-53OZR3UN.js} +3 -3
- package/dist/{wordpress-EM3S3NDA.js → wordpress-2BXU6FDI.js} +3 -3
- package/package.json +1 -1
- package/assets/assets/TrafficSourceDetailPage-BMs9kd7S.js +0 -1
- package/assets/assets/index-Bhpq6fUo.css +0 -1
- package/assets/assets/server-traffic-ykAWQo0I.js +0 -1
- package/dist/intelligence-service-YPKAM4JJ.js +0 -16
|
@@ -17165,7 +17165,7 @@ var resultsClearResponseSchema = z47.object({
|
|
|
17165
17165
|
});
|
|
17166
17166
|
|
|
17167
17167
|
// ../contracts/src/ga.ts
|
|
17168
|
-
import { z as
|
|
17168
|
+
import { z as z52 } from "zod";
|
|
17169
17169
|
|
|
17170
17170
|
// ../contracts/src/traffic-class.ts
|
|
17171
17171
|
import { z as z48 } from "zod";
|
|
@@ -17370,29 +17370,131 @@ function buildStackedDailySeries(points, options) {
|
|
|
17370
17370
|
return { series, otherCount: folded.length, days };
|
|
17371
17371
|
}
|
|
17372
17372
|
|
|
17373
|
+
// ../contracts/src/statistics.ts
|
|
17374
|
+
import { z as z51 } from "zod";
|
|
17375
|
+
function round(value, dp = 4) {
|
|
17376
|
+
const f = 10 ** dp;
|
|
17377
|
+
return (Math.round(value * f) + 0) / f;
|
|
17378
|
+
}
|
|
17379
|
+
function roundSignificant(value, sig = 6) {
|
|
17380
|
+
if (!Number.isFinite(value) || value === 0) return 0;
|
|
17381
|
+
const magnitude = Math.ceil(Math.log10(Math.abs(value)));
|
|
17382
|
+
const factor = 10 ** (sig - magnitude);
|
|
17383
|
+
return (Math.round(value * factor) + 0) / factor;
|
|
17384
|
+
}
|
|
17385
|
+
function shareOf(part, total) {
|
|
17386
|
+
if (!Number.isFinite(part) || !Number.isFinite(total)) return null;
|
|
17387
|
+
if (part <= 0) return 0;
|
|
17388
|
+
return total > 0 ? part / total : null;
|
|
17389
|
+
}
|
|
17390
|
+
function breakdownShares(parts) {
|
|
17391
|
+
const total = parts.reduce((sum, part) => sum + Math.max(0, part), 0);
|
|
17392
|
+
return parts.map((part) => shareOf(part, total) ?? 0);
|
|
17393
|
+
}
|
|
17394
|
+
function median(values) {
|
|
17395
|
+
const sorted = values.filter((value) => Number.isFinite(value)).sort((left, right) => left - right);
|
|
17396
|
+
if (sorted.length === 0) return null;
|
|
17397
|
+
const middle = Math.floor(sorted.length / 2);
|
|
17398
|
+
return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
17399
|
+
}
|
|
17400
|
+
function wilsonInterval(successes, n, z97 = 1.96) {
|
|
17401
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
17402
|
+
const s = Math.max(0, Math.min(successes, n));
|
|
17403
|
+
const p = s / n;
|
|
17404
|
+
const z210 = z97 * z97;
|
|
17405
|
+
const denom = 1 + z210 / n;
|
|
17406
|
+
const center = (p + z210 / (2 * n)) / denom;
|
|
17407
|
+
const margin = z97 / denom * Math.sqrt(p * (1 - p) / n + z210 / (4 * n * n));
|
|
17408
|
+
return {
|
|
17409
|
+
low: round(Math.max(0, center - margin)),
|
|
17410
|
+
high: round(Math.min(1, center + margin))
|
|
17411
|
+
};
|
|
17412
|
+
}
|
|
17413
|
+
var linearTrendSchema = z51.object({
|
|
17414
|
+
/** Change in the fitted value per one-index step. */
|
|
17415
|
+
slope: z51.number(),
|
|
17416
|
+
/** Fitted value at index 0. */
|
|
17417
|
+
intercept: z51.number(),
|
|
17418
|
+
/** Coefficient of determination in [0, 1]. `1` for a series with no variance. */
|
|
17419
|
+
r2: z51.number(),
|
|
17420
|
+
/** Fitted value at the first index. */
|
|
17421
|
+
start: z51.number(),
|
|
17422
|
+
/** Fitted value at the last index. */
|
|
17423
|
+
end: z51.number(),
|
|
17424
|
+
/** Count of finite observations the fit used (not the series length). */
|
|
17425
|
+
n: z51.number(),
|
|
17426
|
+
/**
|
|
17427
|
+
* Index of the first observation the fit used, and of the last.
|
|
17428
|
+
*
|
|
17429
|
+
* `start` / `end` are evaluated AT these indices, not at the series' own ends.
|
|
17430
|
+
* A caller drawing the line must span exactly this range: extending it across
|
|
17431
|
+
* leading or trailing indices the metric has no data for draws a fitted claim
|
|
17432
|
+
* over dates that were never measured.
|
|
17433
|
+
*/
|
|
17434
|
+
startIndex: z51.number(),
|
|
17435
|
+
endIndex: z51.number()
|
|
17436
|
+
});
|
|
17437
|
+
function linearTrend(values) {
|
|
17438
|
+
const points = [];
|
|
17439
|
+
for (const [index, value] of values.entries()) {
|
|
17440
|
+
if (typeof value === "number" && Number.isFinite(value)) points.push({ x: index, y: value });
|
|
17441
|
+
}
|
|
17442
|
+
const n = points.length;
|
|
17443
|
+
if (n < 2) return null;
|
|
17444
|
+
const meanX = points.reduce((sum, p) => sum + p.x, 0) / n;
|
|
17445
|
+
const meanY = points.reduce((sum, p) => sum + p.y, 0) / n;
|
|
17446
|
+
let sxx = 0;
|
|
17447
|
+
let sxy = 0;
|
|
17448
|
+
for (const p of points) {
|
|
17449
|
+
sxx += (p.x - meanX) ** 2;
|
|
17450
|
+
sxy += (p.x - meanX) * (p.y - meanY);
|
|
17451
|
+
}
|
|
17452
|
+
const slope = sxy / sxx;
|
|
17453
|
+
const intercept = meanY - slope * meanX;
|
|
17454
|
+
let ssRes = 0;
|
|
17455
|
+
let ssTot = 0;
|
|
17456
|
+
for (const p of points) {
|
|
17457
|
+
ssRes += (p.y - (slope * p.x + intercept)) ** 2;
|
|
17458
|
+
ssTot += (p.y - meanY) ** 2;
|
|
17459
|
+
}
|
|
17460
|
+
const r2 = ssTot === 0 ? 1 : Math.min(1, Math.max(0, 1 - ssRes / ssTot));
|
|
17461
|
+
const firstX = points[0].x;
|
|
17462
|
+
const lastX = points[n - 1].x;
|
|
17463
|
+
return {
|
|
17464
|
+
slope: roundSignificant(slope),
|
|
17465
|
+
intercept: roundSignificant(intercept),
|
|
17466
|
+
r2: round(r2),
|
|
17467
|
+
start: roundSignificant(slope * firstX + intercept),
|
|
17468
|
+
end: roundSignificant(slope * lastX + intercept),
|
|
17469
|
+
n,
|
|
17470
|
+
startIndex: firstX,
|
|
17471
|
+
endIndex: lastX
|
|
17472
|
+
};
|
|
17473
|
+
}
|
|
17474
|
+
|
|
17373
17475
|
// ../contracts/src/ga.ts
|
|
17374
|
-
var ga4ConnectionDtoSchema =
|
|
17375
|
-
id:
|
|
17376
|
-
projectId:
|
|
17377
|
-
propertyId:
|
|
17378
|
-
clientEmail:
|
|
17379
|
-
connected:
|
|
17380
|
-
createdAt:
|
|
17381
|
-
updatedAt:
|
|
17382
|
-
});
|
|
17383
|
-
var ga4TrafficSnapshotDtoSchema =
|
|
17384
|
-
date:
|
|
17385
|
-
landingPage:
|
|
17386
|
-
sessions:
|
|
17387
|
-
organicSessions:
|
|
17388
|
-
users:
|
|
17389
|
-
});
|
|
17390
|
-
var ga4SourceDimensionSchema =
|
|
17391
|
-
var ga4AiReferralDtoSchema =
|
|
17392
|
-
source:
|
|
17393
|
-
medium:
|
|
17476
|
+
var ga4ConnectionDtoSchema = z52.object({
|
|
17477
|
+
id: z52.string(),
|
|
17478
|
+
projectId: z52.string(),
|
|
17479
|
+
propertyId: z52.string(),
|
|
17480
|
+
clientEmail: z52.string(),
|
|
17481
|
+
connected: z52.boolean(),
|
|
17482
|
+
createdAt: z52.string(),
|
|
17483
|
+
updatedAt: z52.string()
|
|
17484
|
+
});
|
|
17485
|
+
var ga4TrafficSnapshotDtoSchema = z52.object({
|
|
17486
|
+
date: z52.string(),
|
|
17487
|
+
landingPage: z52.string(),
|
|
17488
|
+
sessions: z52.number(),
|
|
17489
|
+
organicSessions: z52.number(),
|
|
17490
|
+
users: z52.number()
|
|
17491
|
+
});
|
|
17492
|
+
var ga4SourceDimensionSchema = z52.enum(["session", "first_user", "manual_utm"]);
|
|
17493
|
+
var ga4AiReferralDtoSchema = z52.object({
|
|
17494
|
+
source: z52.string(),
|
|
17495
|
+
medium: z52.string(),
|
|
17394
17496
|
trafficClass: aiReferralTrafficClassSchema,
|
|
17395
|
-
sessions:
|
|
17497
|
+
sessions: z52.number(),
|
|
17396
17498
|
/**
|
|
17397
17499
|
* @deprecated Never emitted since 4.135.0. Removed in the next major.
|
|
17398
17500
|
*
|
|
@@ -17407,7 +17509,7 @@ var ga4AiReferralDtoSchema = z51.object({
|
|
|
17407
17509
|
* number. Sessions are unaffected: GA4 attributes exactly one landing page
|
|
17408
17510
|
* per session, so the landing-page rows partition the day and do sum.
|
|
17409
17511
|
*/
|
|
17410
|
-
users:
|
|
17512
|
+
users: z52.number().optional(),
|
|
17411
17513
|
/**
|
|
17412
17514
|
* The winning attribution dimension for this (source, medium) tuple — the
|
|
17413
17515
|
* one with the highest session count. GA4 emits one row per dimension
|
|
@@ -17425,33 +17527,33 @@ var ga4AiReferralDtoSchema = z51.object({
|
|
|
17425
17527
|
*/
|
|
17426
17528
|
share: fraction()
|
|
17427
17529
|
});
|
|
17428
|
-
var ga4AiReferralLandingPageDtoSchema =
|
|
17429
|
-
source:
|
|
17430
|
-
medium:
|
|
17530
|
+
var ga4AiReferralLandingPageDtoSchema = z52.object({
|
|
17531
|
+
source: z52.string(),
|
|
17532
|
+
medium: z52.string(),
|
|
17431
17533
|
trafficClass: aiReferralTrafficClassSchema,
|
|
17432
17534
|
/**
|
|
17433
17535
|
* The winning attribution dimension for this (source, medium, landingPage)
|
|
17434
17536
|
* tuple — the one with the highest session count.
|
|
17435
17537
|
*/
|
|
17436
17538
|
sourceDimension: ga4SourceDimensionSchema,
|
|
17437
|
-
landingPage:
|
|
17438
|
-
sessions:
|
|
17539
|
+
landingPage: z52.string(),
|
|
17540
|
+
sessions: z52.number(),
|
|
17439
17541
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17440
|
-
users:
|
|
17542
|
+
users: z52.number().optional()
|
|
17441
17543
|
});
|
|
17442
|
-
var ga4SocialReferralDtoSchema =
|
|
17443
|
-
source:
|
|
17444
|
-
medium:
|
|
17445
|
-
sessions:
|
|
17544
|
+
var ga4SocialReferralDtoSchema = z52.object({
|
|
17545
|
+
source: z52.string(),
|
|
17546
|
+
medium: z52.string(),
|
|
17547
|
+
sessions: z52.number(),
|
|
17446
17548
|
/**
|
|
17447
17549
|
* @deprecated Never emitted by `/ga/traffic`. ga_social_referrals stores
|
|
17448
17550
|
* users as GA's COUNT DISTINCT at (date, source, medium, channel group), so
|
|
17449
17551
|
* summing it across the window counts a returning visitor once per day.
|
|
17450
17552
|
* Optional so existing consumers keep parsing.
|
|
17451
17553
|
*/
|
|
17452
|
-
users:
|
|
17554
|
+
users: z52.number().optional(),
|
|
17453
17555
|
/** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
|
|
17454
|
-
channelGroup:
|
|
17556
|
+
channelGroup: z52.string(),
|
|
17455
17557
|
/**
|
|
17456
17558
|
* This row's sessions as a 0..1 share of the window's social sessions
|
|
17457
17559
|
* (`socialSessions`, which is the sum of these rows), so the rows' shares add
|
|
@@ -17459,51 +17561,51 @@ var ga4SocialReferralDtoSchema = z51.object({
|
|
|
17459
17561
|
*/
|
|
17460
17562
|
share: fraction()
|
|
17461
17563
|
});
|
|
17462
|
-
var ga4SocialPlatformDtoSchema =
|
|
17564
|
+
var ga4SocialPlatformDtoSchema = z52.object({
|
|
17463
17565
|
/** Platform id from `socialPlatformForReferralSource`; null for a source no platform matches. */
|
|
17464
17566
|
platform: socialPlatformSchema.nullable(),
|
|
17465
17567
|
/** The platform's name, or the raw source when `platform` is null. */
|
|
17466
|
-
label:
|
|
17467
|
-
sessions:
|
|
17568
|
+
label: z52.string(),
|
|
17569
|
+
sessions: z52.number(),
|
|
17468
17570
|
/** Sessions outside GA4's Paid Social channel group. */
|
|
17469
|
-
organicSessions:
|
|
17571
|
+
organicSessions: z52.number(),
|
|
17470
17572
|
/** Sessions in GA4's Paid Social channel group. */
|
|
17471
|
-
paidSessions:
|
|
17573
|
+
paidSessions: z52.number(),
|
|
17472
17574
|
/** 0..1 share of `socialSessions`; the groups' shares add up to 1. */
|
|
17473
17575
|
share: fraction(),
|
|
17474
17576
|
/** The grouped `socialReferrals` rows, sessions descending. */
|
|
17475
|
-
sources:
|
|
17577
|
+
sources: z52.array(ga4SocialReferralDtoSchema)
|
|
17476
17578
|
});
|
|
17477
|
-
var ga4AiEngineReferralDtoSchema =
|
|
17579
|
+
var ga4AiEngineReferralDtoSchema = z52.object({
|
|
17478
17580
|
/** Engine id from `aiEngineForReferralSource`; null for the unattributed group. */
|
|
17479
17581
|
engine: aiReferralEngineSchema.nullable(),
|
|
17480
17582
|
/** The engine's name, or `Unattributed AI`. */
|
|
17481
|
-
label:
|
|
17482
|
-
sessions:
|
|
17483
|
-
organicSessions:
|
|
17484
|
-
paidSessions:
|
|
17583
|
+
label: z52.string(),
|
|
17584
|
+
sessions: z52.number(),
|
|
17585
|
+
organicSessions: z52.number(),
|
|
17586
|
+
paidSessions: z52.number(),
|
|
17485
17587
|
/** 0..1 share of the `aiReferrals` rows' sessions, the same base as each row's `share`. */
|
|
17486
17588
|
share: fraction(),
|
|
17487
17589
|
/** The grouped `aiReferrals` rows, sessions descending. */
|
|
17488
|
-
sources:
|
|
17590
|
+
sources: z52.array(ga4AiReferralDtoSchema)
|
|
17489
17591
|
});
|
|
17490
|
-
var ga4ChannelBucketDtoSchema =
|
|
17491
|
-
sessions:
|
|
17592
|
+
var ga4ChannelBucketDtoSchema = z52.object({
|
|
17593
|
+
sessions: z52.number(),
|
|
17492
17594
|
sharePct: percent(),
|
|
17493
|
-
sharePctDisplay:
|
|
17595
|
+
sharePctDisplay: z52.string()
|
|
17494
17596
|
});
|
|
17495
|
-
var ga4ChannelBreakdownDtoSchema =
|
|
17597
|
+
var ga4ChannelBreakdownDtoSchema = z52.object({
|
|
17496
17598
|
organic: ga4ChannelBucketDtoSchema,
|
|
17497
17599
|
social: ga4ChannelBucketDtoSchema,
|
|
17498
17600
|
direct: ga4ChannelBucketDtoSchema,
|
|
17499
17601
|
ai: ga4ChannelBucketDtoSchema,
|
|
17500
17602
|
other: ga4ChannelBucketDtoSchema
|
|
17501
17603
|
});
|
|
17502
|
-
var ga4TrafficSummaryDtoSchema =
|
|
17503
|
-
totalSessions:
|
|
17504
|
-
totalOrganicSessions:
|
|
17604
|
+
var ga4TrafficSummaryDtoSchema = z52.object({
|
|
17605
|
+
totalSessions: z52.number(),
|
|
17606
|
+
totalOrganicSessions: z52.number(),
|
|
17505
17607
|
/** Direct-channel sessions (sessions with no source — bookmarks, typed URLs, AI-driven traffic with stripped referrer). 0 for legacy rows from before the column was added. */
|
|
17506
|
-
totalDirectSessions:
|
|
17608
|
+
totalDirectSessions: z52.number(),
|
|
17507
17609
|
/**
|
|
17508
17610
|
* Null when the range has no un-dimensioned aggregate behind it.
|
|
17509
17611
|
*
|
|
@@ -17512,14 +17614,14 @@ var ga4TrafficSummaryDtoSchema = z51.object({
|
|
|
17512
17614
|
* windows have a precomputed deduplicated row; an explicit calendar range does
|
|
17513
17615
|
* not, and reports the figure as unavailable rather than as an inflated sum.
|
|
17514
17616
|
*/
|
|
17515
|
-
totalUsers:
|
|
17516
|
-
topPages:
|
|
17517
|
-
landingPage:
|
|
17518
|
-
sessions:
|
|
17519
|
-
organicSessions:
|
|
17617
|
+
totalUsers: z52.number().nullable(),
|
|
17618
|
+
topPages: z52.array(z52.object({
|
|
17619
|
+
landingPage: z52.string(),
|
|
17620
|
+
sessions: z52.number(),
|
|
17621
|
+
organicSessions: z52.number(),
|
|
17520
17622
|
/** Per-page Direct-channel sessions. 0 for legacy rows. */
|
|
17521
|
-
directSessions:
|
|
17522
|
-
users:
|
|
17623
|
+
directSessions: z52.number(),
|
|
17624
|
+
users: z52.number(),
|
|
17523
17625
|
/**
|
|
17524
17626
|
* Organic search sessions as a 0..1 share of this page's sessions. 0 when
|
|
17525
17627
|
* the page has no organic sessions; null when organic sessions exist with
|
|
@@ -17527,49 +17629,49 @@ var ga4TrafficSummaryDtoSchema = z51.object({
|
|
|
17527
17629
|
*/
|
|
17528
17630
|
organicShare: fraction().nullable()
|
|
17529
17631
|
})),
|
|
17530
|
-
aiReferrals:
|
|
17531
|
-
aiReferralLandingPages:
|
|
17632
|
+
aiReferrals: z52.array(ga4AiReferralDtoSchema),
|
|
17633
|
+
aiReferralLandingPages: z52.array(ga4AiReferralLandingPageDtoSchema),
|
|
17532
17634
|
/** Deduped AI session total: MAX(sessions) per date+source across attribution dimensions, then summed. Cross-cutting: can overlap with Direct/Organic/Social via firstUserSource. */
|
|
17533
|
-
aiSessionsDeduped:
|
|
17635
|
+
aiSessionsDeduped: z52.number(),
|
|
17534
17636
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17535
|
-
aiUsersDeduped:
|
|
17637
|
+
aiUsersDeduped: z52.number().optional(),
|
|
17536
17638
|
/** Deduped AI sessions whose attribution carries paid intent. */
|
|
17537
|
-
paidAiSessionsDeduped:
|
|
17639
|
+
paidAiSessionsDeduped: z52.number(),
|
|
17538
17640
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17539
|
-
paidAiUsersDeduped:
|
|
17641
|
+
paidAiUsersDeduped: z52.number().optional(),
|
|
17540
17642
|
/** Deduped AI sessions without paid intent evidence. */
|
|
17541
|
-
organicAiSessionsDeduped:
|
|
17643
|
+
organicAiSessionsDeduped: z52.number(),
|
|
17542
17644
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17543
|
-
organicAiUsersDeduped:
|
|
17645
|
+
organicAiUsersDeduped: z52.number().optional(),
|
|
17544
17646
|
/** AI sessions whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals; `channelBreakdown` removes those overlaps for display. */
|
|
17545
|
-
aiSessionsBySession:
|
|
17647
|
+
aiSessionsBySession: z52.number(),
|
|
17546
17648
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17547
|
-
aiUsersBySession:
|
|
17649
|
+
aiUsersBySession: z52.number().optional(),
|
|
17548
17650
|
/** Session-source-only paid AI sessions. */
|
|
17549
|
-
paidAiSessionsBySession:
|
|
17651
|
+
paidAiSessionsBySession: z52.number(),
|
|
17550
17652
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17551
|
-
paidAiUsersBySession:
|
|
17653
|
+
paidAiUsersBySession: z52.number().optional(),
|
|
17552
17654
|
/** Session-source-only organic/non-paid AI sessions. */
|
|
17553
|
-
organicAiSessionsBySession:
|
|
17655
|
+
organicAiSessionsBySession: z52.number(),
|
|
17554
17656
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
17555
|
-
organicAiUsersBySession:
|
|
17657
|
+
organicAiUsersBySession: z52.number().optional(),
|
|
17556
17658
|
/**
|
|
17557
17659
|
* `aiReferrals` grouped by engine, sessions descending, with the unattributed
|
|
17558
17660
|
* group last. The groups' sessions add up to the rows' sessions.
|
|
17559
17661
|
*/
|
|
17560
|
-
aiEngines:
|
|
17561
|
-
socialReferrals:
|
|
17662
|
+
aiEngines: z52.array(ga4AiEngineReferralDtoSchema),
|
|
17663
|
+
socialReferrals: z52.array(ga4SocialReferralDtoSchema),
|
|
17562
17664
|
/** `socialReferrals` grouped by platform, sessions descending; the groups' sessions add up to `socialSessions`. */
|
|
17563
|
-
socialPlatforms:
|
|
17665
|
+
socialPlatforms: z52.array(ga4SocialPlatformDtoSchema),
|
|
17564
17666
|
/**
|
|
17565
17667
|
* Daily social sessions by platform over the same window as every other
|
|
17566
17668
|
* figure here: the five largest platforms, then the rest as `other`.
|
|
17567
17669
|
*/
|
|
17568
17670
|
socialPlatformDaily: stackedDailySeriesSchema,
|
|
17569
17671
|
/** Total social sessions (session-scoped, no cross-dimension dedup needed). */
|
|
17570
|
-
socialSessions:
|
|
17672
|
+
socialSessions: z52.number(),
|
|
17571
17673
|
/** Social sessions in GA4's Paid Social channel group. */
|
|
17572
|
-
paidSocialSessions:
|
|
17674
|
+
paidSocialSessions: z52.number(),
|
|
17573
17675
|
/** `paidSocialSessions` as a 0..1 share of `socialSessions`; 0 with no social sessions. */
|
|
17574
17676
|
paidSocialShare: fraction(),
|
|
17575
17677
|
/** Total social users (session-scoped, no cross-dimension dedup needed). */
|
|
@@ -17578,7 +17680,7 @@ var ga4TrafficSummaryDtoSchema = z51.object({
|
|
|
17578
17680
|
* COUNT DISTINCT at (date, source, medium, channel group), so summing it
|
|
17579
17681
|
* across the window counts a returning visitor once per day.
|
|
17580
17682
|
*/
|
|
17581
|
-
socialUsers:
|
|
17683
|
+
socialUsers: z52.number().optional(),
|
|
17582
17684
|
/** Five disjoint buckets used for the channel breakdown. Known AI session-source matches are removed from their native GA4 bucket before shares are computed. */
|
|
17583
17685
|
channelBreakdown: ga4ChannelBreakdownDtoSchema,
|
|
17584
17686
|
/** Organic sessions as a percentage of total sessions (0–100, at wire precision). */
|
|
@@ -17600,50 +17702,50 @@ var ga4TrafficSummaryDtoSchema = z51.object({
|
|
|
17600
17702
|
/** Social sessions as a percentage of total sessions (0–100, at wire precision). */
|
|
17601
17703
|
socialSharePct: percent(),
|
|
17602
17704
|
/** Display string for organicSharePct: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17603
|
-
organicSharePctDisplay:
|
|
17705
|
+
organicSharePctDisplay: z52.string(),
|
|
17604
17706
|
/** Display string for aiSharePct: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17605
|
-
aiSharePctDisplay:
|
|
17707
|
+
aiSharePctDisplay: z52.string(),
|
|
17606
17708
|
/** Display string for aiSharePctBySession: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17607
|
-
aiSharePctBySessionDisplay:
|
|
17709
|
+
aiSharePctBySessionDisplay: z52.string(),
|
|
17608
17710
|
/** Display string for paidAiSharePct. */
|
|
17609
|
-
paidAiSharePctDisplay:
|
|
17711
|
+
paidAiSharePctDisplay: z52.string(),
|
|
17610
17712
|
/** Display string for paidAiSharePctBySession. */
|
|
17611
|
-
paidAiSharePctBySessionDisplay:
|
|
17713
|
+
paidAiSharePctBySessionDisplay: z52.string(),
|
|
17612
17714
|
/** Display string for organicAiSharePct. */
|
|
17613
|
-
organicAiSharePctDisplay:
|
|
17715
|
+
organicAiSharePctDisplay: z52.string(),
|
|
17614
17716
|
/** Display string for organicAiSharePctBySession. */
|
|
17615
|
-
organicAiSharePctBySessionDisplay:
|
|
17717
|
+
organicAiSharePctBySessionDisplay: z52.string(),
|
|
17616
17718
|
/** Display string for directSharePct: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17617
|
-
directSharePctDisplay:
|
|
17719
|
+
directSharePctDisplay: z52.string(),
|
|
17618
17720
|
/** Display string for socialSharePct: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17619
|
-
socialSharePctDisplay:
|
|
17721
|
+
socialSharePctDisplay: z52.string(),
|
|
17620
17722
|
/** Sessions not covered by Organic, Social, Direct, or AI (session) channels — e.g. Referral, Email, Paid Search, Display. Always non-negative; clamped to 0 when the four disjoint channels sum above total (rounding edge). */
|
|
17621
|
-
otherSessions:
|
|
17723
|
+
otherSessions: z52.number(),
|
|
17622
17724
|
/** Other sessions as a percentage of total sessions (0–100, at wire precision). */
|
|
17623
17725
|
otherSharePct: percent(),
|
|
17624
17726
|
/** Display string for otherSharePct: the unrounded share through formatPercent ('12.5%', '<0.1%' for a non-zero share below one decimal), '0%' with no sessions, or '—' when sessions exist but total is unknown (partial sync). */
|
|
17625
|
-
otherSharePctDisplay:
|
|
17626
|
-
lastSyncedAt:
|
|
17627
|
-
});
|
|
17628
|
-
var ga4StatusDtoSchema =
|
|
17629
|
-
connected:
|
|
17630
|
-
propertyId:
|
|
17631
|
-
clientEmail:
|
|
17632
|
-
authMethod:
|
|
17633
|
-
lastSyncedAt:
|
|
17634
|
-
createdAt:
|
|
17635
|
-
updatedAt:
|
|
17636
|
-
});
|
|
17637
|
-
var ga4PropertySummaryDtoSchema =
|
|
17638
|
-
propertyId:
|
|
17639
|
-
displayName:
|
|
17727
|
+
otherSharePctDisplay: z52.string(),
|
|
17728
|
+
lastSyncedAt: z52.string().nullable()
|
|
17729
|
+
});
|
|
17730
|
+
var ga4StatusDtoSchema = z52.object({
|
|
17731
|
+
connected: z52.boolean(),
|
|
17732
|
+
propertyId: z52.string().nullable(),
|
|
17733
|
+
clientEmail: z52.string().nullable(),
|
|
17734
|
+
authMethod: z52.enum(["service-account", "oauth"]).nullable(),
|
|
17735
|
+
lastSyncedAt: z52.string().nullable(),
|
|
17736
|
+
createdAt: z52.string().nullable().optional(),
|
|
17737
|
+
updatedAt: z52.string().nullable().optional()
|
|
17738
|
+
});
|
|
17739
|
+
var ga4PropertySummaryDtoSchema = z52.object({
|
|
17740
|
+
propertyId: z52.string(),
|
|
17741
|
+
displayName: z52.string(),
|
|
17640
17742
|
/** GA4 account that owns the property. Two accounts can hold like-named properties. */
|
|
17641
|
-
accountName:
|
|
17743
|
+
accountName: z52.string()
|
|
17642
17744
|
});
|
|
17643
|
-
var ga4PropertiesDtoSchema =
|
|
17644
|
-
properties:
|
|
17745
|
+
var ga4PropertiesDtoSchema = z52.object({
|
|
17746
|
+
properties: z52.array(ga4PropertySummaryDtoSchema)
|
|
17645
17747
|
});
|
|
17646
|
-
var gaSearchLandingWindowSchema =
|
|
17748
|
+
var gaSearchLandingWindowSchema = z52.enum(WINDOW_SETS.gaSearchLanding);
|
|
17647
17749
|
var GA_SEARCH_LANDING_WINDOWS = gaSearchLandingWindowSchema.options;
|
|
17648
17750
|
var GA_SEARCH_LANDING_WINDOW_DAYS = {
|
|
17649
17751
|
"7d": 7,
|
|
@@ -17657,124 +17759,124 @@ function gaSearchLandingPageLabel(landingPage) {
|
|
|
17657
17759
|
return landingPage === "" ? GA_SEARCH_LANDING_EMPTY_PAGE_LABEL : landingPage;
|
|
17658
17760
|
}
|
|
17659
17761
|
var GA_SEARCH_LANDING_MAX_LIMIT = 1e3;
|
|
17660
|
-
var gaSearchLandingStatusSchema =
|
|
17661
|
-
var gaSearchLandingMetricsSchema =
|
|
17662
|
-
organicGoogleSearchClicks:
|
|
17663
|
-
organicGoogleSearchImpressions:
|
|
17762
|
+
var gaSearchLandingStatusSchema = z52.enum(["never-synced", "ready", "unavailable", "error"]);
|
|
17763
|
+
var gaSearchLandingMetricsSchema = z52.object({
|
|
17764
|
+
organicGoogleSearchClicks: z52.number().int().nonnegative(),
|
|
17765
|
+
organicGoogleSearchImpressions: z52.number().int().nonnegative(),
|
|
17664
17766
|
/** GA4's own click-through rate (0..1). Null when there were no impressions. */
|
|
17665
|
-
organicGoogleSearchClickThroughRate: fraction(
|
|
17767
|
+
organicGoogleSearchClickThroughRate: fraction(z52.number().min(0).max(1)).nullable(),
|
|
17666
17768
|
/** GA4's own average position. Null when there were no impressions. */
|
|
17667
|
-
organicGoogleSearchAveragePosition:
|
|
17769
|
+
organicGoogleSearchAveragePosition: z52.number().nonnegative().nullable(),
|
|
17668
17770
|
/**
|
|
17669
17771
|
* GA4's plain `activeUsers` from the same request, which is what GA4's own
|
|
17670
17772
|
* report shows in this column (verified against the GA4 UI). Not limited to
|
|
17671
17773
|
* Google organic sessions.
|
|
17672
17774
|
*/
|
|
17673
|
-
activeUsers:
|
|
17775
|
+
activeUsers: z52.number().int().nonnegative()
|
|
17674
17776
|
});
|
|
17675
17777
|
var gaSearchLandingPageRowSchema = gaSearchLandingMetricsSchema.extend({
|
|
17676
17778
|
/** GA4's `landingPagePlusQueryString`, exactly as reported (never normalized). */
|
|
17677
|
-
landingPage:
|
|
17779
|
+
landingPage: z52.string()
|
|
17678
17780
|
});
|
|
17679
|
-
var gaSearchConsoleLinkStateSchema =
|
|
17680
|
-
var gaSearchLandingPagesResponseSchema =
|
|
17681
|
-
source:
|
|
17781
|
+
var gaSearchConsoleLinkStateSchema = z52.enum(["has-data", "not-linked", "no-search-data", "unknown"]);
|
|
17782
|
+
var gaSearchLandingPagesResponseSchema = z52.object({
|
|
17783
|
+
source: z52.literal("ga4-search-console-link"),
|
|
17682
17784
|
status: gaSearchLandingStatusSchema,
|
|
17683
17785
|
/** The last failed attempt's message (Google's own text for `unavailable`). */
|
|
17684
|
-
error:
|
|
17786
|
+
error: z52.string().nullable(),
|
|
17685
17787
|
/** When the stored snapshot was written. Null when none exists. */
|
|
17686
|
-
syncedAt:
|
|
17788
|
+
syncedAt: z52.string().datetime().nullable(),
|
|
17687
17789
|
/** When a sync last tried to refresh the snapshot, successful or not. */
|
|
17688
|
-
attemptedAt:
|
|
17790
|
+
attemptedAt: z52.string().datetime().nullable(),
|
|
17689
17791
|
window: gaSearchLandingWindowSchema,
|
|
17690
17792
|
/** Inclusive first day of the stored window, in the property's time zone. */
|
|
17691
|
-
windowStart:
|
|
17793
|
+
windowStart: z52.iso.date().nullable(),
|
|
17692
17794
|
/** Inclusive last day of the stored window (yesterday at sync time). */
|
|
17693
|
-
windowEnd:
|
|
17694
|
-
windowDays:
|
|
17795
|
+
windowEnd: z52.iso.date().nullable(),
|
|
17796
|
+
windowDays: z52.number().int().positive().nullable(),
|
|
17695
17797
|
/** GA4 property reporting time zone the window dates are in. */
|
|
17696
|
-
timeZone:
|
|
17697
|
-
subjectToThresholding:
|
|
17698
|
-
dataLossFromOtherRow:
|
|
17798
|
+
timeZone: z52.string().nullable(),
|
|
17799
|
+
subjectToThresholding: z52.boolean(),
|
|
17800
|
+
dataLossFromOtherRow: z52.boolean(),
|
|
17699
17801
|
/** GA4's own TOTAL row for the window. Never a sum of `rows`. Null when no snapshot exists. */
|
|
17700
17802
|
total: gaSearchLandingMetricsSchema.nullable(),
|
|
17701
17803
|
/** Rows GA4 reported for the window. Can exceed `totalRows` when `rowsCapped`. */
|
|
17702
|
-
reportRowCount:
|
|
17804
|
+
reportRowCount: z52.number().int().nonnegative().nullable(),
|
|
17703
17805
|
/** True when GA4 reported more rows than were stored (the per-window row cap). */
|
|
17704
|
-
rowsCapped:
|
|
17806
|
+
rowsCapped: z52.boolean(),
|
|
17705
17807
|
/** Stored rows for the window, the population `limit` / `offset` page over. */
|
|
17706
|
-
totalRows:
|
|
17707
|
-
limit:
|
|
17708
|
-
offset:
|
|
17808
|
+
totalRows: z52.number().int().nonnegative(),
|
|
17809
|
+
limit: z52.number().int().positive(),
|
|
17810
|
+
offset: z52.number().int().nonnegative(),
|
|
17709
17811
|
/** Ordered by clicks, then impressions (both descending), then landing page. */
|
|
17710
|
-
rows:
|
|
17812
|
+
rows: z52.array(gaSearchLandingPageRowSchema),
|
|
17711
17813
|
/**
|
|
17712
17814
|
* Whether the window's GA4 report has Search Console data, compared with
|
|
17713
17815
|
* Canonry's own Search Console data for the same days. Null when no window
|
|
17714
17816
|
* is stored.
|
|
17715
17817
|
*/
|
|
17716
|
-
searchConsoleLink:
|
|
17818
|
+
searchConsoleLink: z52.object({
|
|
17717
17819
|
state: gaSearchConsoleLinkStateSchema,
|
|
17718
17820
|
/** Search Console impressions Canonry stores for the window's days; null when it has none for them. */
|
|
17719
|
-
searchConsoleImpressions:
|
|
17821
|
+
searchConsoleImpressions: z52.number().int().nonnegative().nullable()
|
|
17720
17822
|
}).nullable()
|
|
17721
17823
|
});
|
|
17722
17824
|
function gaSearchLandingHasSearchData(total) {
|
|
17723
17825
|
return total.organicGoogleSearchClicks > 0 || total.organicGoogleSearchImpressions > 0;
|
|
17724
17826
|
}
|
|
17725
|
-
var gaSearchLandingSyncResultSchema =
|
|
17726
|
-
status:
|
|
17827
|
+
var gaSearchLandingSyncResultSchema = z52.object({
|
|
17828
|
+
status: z52.enum(["ready", "unavailable", "error"]),
|
|
17727
17829
|
/** Windows written by this sync, empty unless `ready`. */
|
|
17728
|
-
windows:
|
|
17830
|
+
windows: z52.array(z52.object({
|
|
17729
17831
|
window: gaSearchLandingWindowSchema,
|
|
17730
|
-
rowCount:
|
|
17731
|
-
reportRowCount:
|
|
17732
|
-
rowsCapped:
|
|
17832
|
+
rowCount: z52.number().int().nonnegative(),
|
|
17833
|
+
reportRowCount: z52.number().int().nonnegative(),
|
|
17834
|
+
rowsCapped: z52.boolean()
|
|
17733
17835
|
})),
|
|
17734
17836
|
/** Landing-page rows written across every window. */
|
|
17735
|
-
rowCount:
|
|
17736
|
-
error:
|
|
17837
|
+
rowCount: z52.number().int().nonnegative(),
|
|
17838
|
+
error: z52.string().optional()
|
|
17737
17839
|
});
|
|
17738
|
-
var gaSyncOnlySchema =
|
|
17739
|
-
var ga4SyncResponseDtoSchema =
|
|
17740
|
-
synced:
|
|
17741
|
-
rowCount:
|
|
17742
|
-
aiReferralCount:
|
|
17743
|
-
socialReferralCount:
|
|
17840
|
+
var gaSyncOnlySchema = z52.enum(["traffic", "ai", "social", "search-landing"]);
|
|
17841
|
+
var ga4SyncResponseDtoSchema = z52.object({
|
|
17842
|
+
synced: z52.boolean(),
|
|
17843
|
+
rowCount: z52.number().int().nonnegative(),
|
|
17844
|
+
aiReferralCount: z52.number().int().nonnegative(),
|
|
17845
|
+
socialReferralCount: z52.number().int().nonnegative(),
|
|
17744
17846
|
/**
|
|
17745
17847
|
* The window that was ACTUALLY fetched and written, in days — the request's
|
|
17746
17848
|
* `days` bounded to GA4's supported sync range (1–90). Read this, not
|
|
17747
17849
|
* `requestedDays`, when reporting or reasoning about coverage: a
|
|
17748
17850
|
* `--days 500` sync writes 90 days, and this field says 90.
|
|
17749
17851
|
*/
|
|
17750
|
-
days:
|
|
17852
|
+
days: z52.number().int().nonnegative(),
|
|
17751
17853
|
/** The window the caller asked for, before bounding. Equals `days` unless `clamped`. */
|
|
17752
|
-
requestedDays:
|
|
17854
|
+
requestedDays: z52.number().int().nonnegative(),
|
|
17753
17855
|
/**
|
|
17754
17856
|
* True when `requestedDays` fell outside GA4's supported range and `days`
|
|
17755
17857
|
* differs from it — i.e. the synced history is not the range requested.
|
|
17756
17858
|
*/
|
|
17757
|
-
clamped:
|
|
17758
|
-
syncedAt:
|
|
17759
|
-
measurement:
|
|
17760
|
-
acquisition:
|
|
17761
|
-
leads:
|
|
17762
|
-
days:
|
|
17763
|
-
status:
|
|
17764
|
-
rowCount:
|
|
17765
|
-
attributionScope:
|
|
17766
|
-
error:
|
|
17859
|
+
clamped: z52.boolean(),
|
|
17860
|
+
syncedAt: z52.string(),
|
|
17861
|
+
measurement: z52.object({
|
|
17862
|
+
acquisition: z52.object({ days: z52.number().int().nonnegative(), status: z52.enum(["ready", "error"]), rowCount: z52.number().int().nonnegative(), error: z52.string().optional() }),
|
|
17863
|
+
leads: z52.object({
|
|
17864
|
+
days: z52.number().int().nonnegative(),
|
|
17865
|
+
status: z52.enum(["ready", "error", "not-configured"]),
|
|
17866
|
+
rowCount: z52.number().int().nonnegative(),
|
|
17867
|
+
attributionScope: z52.enum(["landing-page", "channel"]).optional(),
|
|
17868
|
+
error: z52.string().optional(),
|
|
17767
17869
|
/** The GA4 events this sync counted: the configured lead events plus the property's key events. */
|
|
17768
|
-
eventNames:
|
|
17870
|
+
eventNames: z52.array(z52.string()).optional(),
|
|
17769
17871
|
/**
|
|
17770
17872
|
* The property's key-event read. `read` lists them; `error` keeps the
|
|
17771
17873
|
* previous successful list and names the failure; `disabled` means the
|
|
17772
17874
|
* project counts only its configured lead events.
|
|
17773
17875
|
*/
|
|
17774
|
-
keyEvents:
|
|
17775
|
-
status:
|
|
17776
|
-
names:
|
|
17777
|
-
error:
|
|
17876
|
+
keyEvents: z52.object({
|
|
17877
|
+
status: z52.enum(["read", "error", "disabled"]),
|
|
17878
|
+
names: z52.array(z52.string()),
|
|
17879
|
+
error: z52.string().optional()
|
|
17778
17880
|
}).optional()
|
|
17779
17881
|
}),
|
|
17780
17882
|
/**
|
|
@@ -17792,18 +17894,18 @@ var ga4SyncResponseDtoSchema = z51.object({
|
|
|
17792
17894
|
* or `unavailable` attempt is left out and reported in
|
|
17793
17895
|
* `measurement.searchLandingPages`.
|
|
17794
17896
|
*/
|
|
17795
|
-
syncedComponents:
|
|
17897
|
+
syncedComponents: z52.array(z52.string()).optional()
|
|
17796
17898
|
});
|
|
17797
|
-
var gaMoverChangeBasisSchema =
|
|
17899
|
+
var gaMoverChangeBasisSchema = z52.enum(["new", "small-base", "percent"]);
|
|
17798
17900
|
var GaMoverChangeBases = gaMoverChangeBasisSchema.enum;
|
|
17799
|
-
var gaSourceMoverSchema =
|
|
17800
|
-
source:
|
|
17901
|
+
var gaSourceMoverSchema = z52.object({
|
|
17902
|
+
source: z52.string(),
|
|
17801
17903
|
/** Sessions from this source in the last 7 days. */
|
|
17802
|
-
sessions7d:
|
|
17904
|
+
sessions7d: z52.number(),
|
|
17803
17905
|
/** Sessions from this source in the 7 days before that. */
|
|
17804
|
-
sessionsPrev7d:
|
|
17906
|
+
sessionsPrev7d: z52.number(),
|
|
17805
17907
|
/** Signed session change, `sessions7d - sessionsPrev7d`. The mover is the source whose change is largest in size. */
|
|
17806
|
-
changeSessions:
|
|
17908
|
+
changeSessions: z52.number(),
|
|
17807
17909
|
/**
|
|
17808
17910
|
* Signed whole-percent change against the prior 7 days (`150` = +150%, `-100`
|
|
17809
17911
|
* = the source stopped sending sessions). Null when the prior 7 days had no
|
|
@@ -17812,29 +17914,29 @@ var gaSourceMoverSchema = z51.object({
|
|
|
17812
17914
|
changePct: percent().nullable(),
|
|
17813
17915
|
changeBasis: gaMoverChangeBasisSchema
|
|
17814
17916
|
});
|
|
17815
|
-
var gaSocialReferralTrendResponseSchema =
|
|
17816
|
-
socialSessions7d:
|
|
17817
|
-
socialSessionsPrev7d:
|
|
17917
|
+
var gaSocialReferralTrendResponseSchema = z52.object({
|
|
17918
|
+
socialSessions7d: z52.number(),
|
|
17919
|
+
socialSessionsPrev7d: z52.number(),
|
|
17818
17920
|
/** Signed whole-percent change of the last 7 days against the 7 before. Null when the prior 7 days had no sessions. */
|
|
17819
17921
|
trend7dPct: percent().nullable(),
|
|
17820
|
-
socialSessions30d:
|
|
17821
|
-
socialSessionsPrev30d:
|
|
17922
|
+
socialSessions30d: z52.number(),
|
|
17923
|
+
socialSessionsPrev30d: z52.number(),
|
|
17822
17924
|
/** Signed whole-percent change of the last 30 days against the 30 before. Null when the prior 30 days had no sessions. */
|
|
17823
17925
|
trend30dPct: percent().nullable(),
|
|
17824
17926
|
/** Social source with the largest session change in the last 7 days against the 7 before. Null when no source moved. */
|
|
17825
17927
|
biggestMover: gaSourceMoverSchema.nullable()
|
|
17826
17928
|
});
|
|
17827
|
-
var gaChannelTrendSchema =
|
|
17828
|
-
sessions7d:
|
|
17829
|
-
sessionsPrev7d:
|
|
17929
|
+
var gaChannelTrendSchema = z52.object({
|
|
17930
|
+
sessions7d: z52.number(),
|
|
17931
|
+
sessionsPrev7d: z52.number(),
|
|
17830
17932
|
/** Signed whole-percent change of the last 7 days against the 7 before. Null when the prior 7 days had no sessions. */
|
|
17831
17933
|
trend7dPct: percent().nullable(),
|
|
17832
|
-
sessions30d:
|
|
17833
|
-
sessionsPrev30d:
|
|
17934
|
+
sessions30d: z52.number(),
|
|
17935
|
+
sessionsPrev30d: z52.number(),
|
|
17834
17936
|
/** Signed whole-percent change of the last 30 days against the 30 before. Null when the prior 30 days had no sessions. */
|
|
17835
17937
|
trend30dPct: percent().nullable()
|
|
17836
17938
|
});
|
|
17837
|
-
var gaAttributionTrendResponseSchema =
|
|
17939
|
+
var gaAttributionTrendResponseSchema = z52.object({
|
|
17838
17940
|
organic: gaChannelTrendSchema,
|
|
17839
17941
|
/** AI session trend, scoped to sessionSource-only matches so it lines up with the disjoint AI cell in the channel breakdown. */
|
|
17840
17942
|
ai: gaChannelTrendSchema,
|
|
@@ -17846,23 +17948,23 @@ var gaAttributionTrendResponseSchema = z51.object({
|
|
|
17846
17948
|
/** Social source with the largest session change in the last 7 days against the 7 before. Null when no source moved. */
|
|
17847
17949
|
socialBiggestMover: gaSourceMoverSchema.nullable()
|
|
17848
17950
|
});
|
|
17849
|
-
var gaOverviewValuesSchema =
|
|
17850
|
-
activeUsers:
|
|
17851
|
-
newUsers:
|
|
17852
|
-
totalUsers:
|
|
17853
|
-
sessions:
|
|
17854
|
-
organicSessions:
|
|
17855
|
-
views:
|
|
17856
|
-
eventCount:
|
|
17951
|
+
var gaOverviewValuesSchema = z52.object({
|
|
17952
|
+
activeUsers: z52.number().int().nonnegative().nullable(),
|
|
17953
|
+
newUsers: z52.number().int().nonnegative().nullable(),
|
|
17954
|
+
totalUsers: z52.number().int().nonnegative().nullable(),
|
|
17955
|
+
sessions: z52.number().int().nonnegative().nullable(),
|
|
17956
|
+
organicSessions: z52.number().int().nonnegative().nullable(),
|
|
17957
|
+
views: z52.number().int().nonnegative().nullable(),
|
|
17958
|
+
eventCount: z52.number().int().nonnegative().nullable(),
|
|
17857
17959
|
/** GA4 counts a key event once per session when the property says so, so this can be a decimal. */
|
|
17858
|
-
keyEvents:
|
|
17960
|
+
keyEvents: z52.number().nonnegative().nullable(),
|
|
17859
17961
|
engagementRate: fraction().nullable(),
|
|
17860
17962
|
bounceRate: fraction().nullable(),
|
|
17861
|
-
averageEngagementTimeSeconds:
|
|
17963
|
+
averageEngagementTimeSeconds: z52.number().nonnegative().nullable()
|
|
17862
17964
|
});
|
|
17863
17965
|
var gaOverviewMetricKeySchema = gaOverviewValuesSchema.keyof();
|
|
17864
17966
|
var GaOverviewMetricKeys = gaOverviewMetricKeySchema.enum;
|
|
17865
|
-
var gaOverviewChangeSchema =
|
|
17967
|
+
var gaOverviewChangeSchema = z52.object({
|
|
17866
17968
|
activeUsers: percent().nullable(),
|
|
17867
17969
|
newUsers: percent().nullable(),
|
|
17868
17970
|
totalUsers: percent().nullable(),
|
|
@@ -17897,19 +17999,19 @@ function gaOverviewComparisonRanges(window, now = /* @__PURE__ */ new Date(), ti
|
|
|
17897
17999
|
};
|
|
17898
18000
|
}
|
|
17899
18001
|
var GaOverviewPeriods = { current: "current", previous: "previous" };
|
|
17900
|
-
var gaOverviewPeriodSchema =
|
|
18002
|
+
var gaOverviewPeriodSchema = z52.object({
|
|
17901
18003
|
/** Inclusive. Null when the window has never been synced with the overview metrics. */
|
|
17902
|
-
startDate:
|
|
17903
|
-
endDate:
|
|
18004
|
+
startDate: z52.string().nullable(),
|
|
18005
|
+
endDate: z52.string().nullable()
|
|
17904
18006
|
});
|
|
17905
|
-
var gaOverviewDaySchema =
|
|
17906
|
-
date:
|
|
18007
|
+
var gaOverviewDaySchema = z52.object({
|
|
18008
|
+
date: z52.string(),
|
|
17907
18009
|
/** The day of the previous period in the same position: the window's first day lines up with its first. */
|
|
17908
|
-
previousDate:
|
|
18010
|
+
previousDate: z52.string(),
|
|
17909
18011
|
values: gaOverviewValuesSchema,
|
|
17910
18012
|
previousValues: gaOverviewValuesSchema
|
|
17911
18013
|
});
|
|
17912
|
-
var gaOverviewResponseSchema =
|
|
18014
|
+
var gaOverviewResponseSchema = z52.object({
|
|
17913
18015
|
window: metricsWindowSchema,
|
|
17914
18016
|
current: gaOverviewPeriodSchema,
|
|
17915
18017
|
/** The period just before `current`, of the same length. */
|
|
@@ -17923,9 +18025,9 @@ var gaOverviewResponseSchema = z51.object({
|
|
|
17923
18025
|
*/
|
|
17924
18026
|
changePct: gaOverviewChangeSchema,
|
|
17925
18027
|
/** One entry per day of `current`, oldest first. */
|
|
17926
|
-
days:
|
|
18028
|
+
days: z52.array(gaOverviewDaySchema),
|
|
17927
18029
|
/** When GA4 last reported this window's totals. Null when it never has. */
|
|
17928
|
-
syncedAt:
|
|
18030
|
+
syncedAt: z52.string().nullable()
|
|
17929
18031
|
});
|
|
17930
18032
|
var GaOverviewUnits = { count: "count", fraction: "fraction", seconds: "seconds" };
|
|
17931
18033
|
var GaOverviewBetter = { higher: "higher", lower: "lower" };
|
|
@@ -17964,128 +18066,141 @@ var gaTrafficResponseSchema = ga4TrafficSummaryDtoSchema.extend({
|
|
|
17964
18066
|
* Read every share against this window. The share fields divide a channel
|
|
17965
18067
|
* count by `totalSessions`; both come from these dates and only these dates.
|
|
17966
18068
|
*/
|
|
17967
|
-
windowStart:
|
|
18069
|
+
windowStart: z52.string().nullable(),
|
|
17968
18070
|
/** Inclusive end (YYYY-MM-DD) of the measured window. `null` when open-ended. */
|
|
17969
|
-
windowEnd:
|
|
18071
|
+
windowEnd: z52.string().nullable(),
|
|
17970
18072
|
/**
|
|
17971
18073
|
* Calendar days the measured window covers, counting both ends. `null` when
|
|
17972
18074
|
* either bound is open — an unknown span is reported as unknown rather than
|
|
17973
18075
|
* guessed.
|
|
17974
18076
|
*/
|
|
17975
|
-
windowDays:
|
|
18077
|
+
windowDays: z52.number().nullable(),
|
|
17976
18078
|
/** Alias of `windowStart`, retained for callers that predate it. */
|
|
17977
|
-
periodStart:
|
|
18079
|
+
periodStart: z52.string().nullable(),
|
|
17978
18080
|
/** Alias of `windowEnd`, retained for callers that predate it. */
|
|
17979
|
-
periodEnd:
|
|
18081
|
+
periodEnd: z52.string().nullable()
|
|
17980
18082
|
});
|
|
17981
|
-
var ga4AiReferralHistoryEntrySchema =
|
|
17982
|
-
date:
|
|
17983
|
-
source:
|
|
17984
|
-
medium:
|
|
18083
|
+
var ga4AiReferralHistoryEntrySchema = z52.object({
|
|
18084
|
+
date: z52.string(),
|
|
18085
|
+
source: z52.string(),
|
|
18086
|
+
medium: z52.string(),
|
|
17985
18087
|
trafficClass: aiReferralTrafficClassSchema,
|
|
17986
|
-
landingPage:
|
|
17987
|
-
sessions:
|
|
18088
|
+
landingPage: z52.string(),
|
|
18089
|
+
sessions: z52.number(),
|
|
17988
18090
|
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.180.6. */
|
|
17989
|
-
users:
|
|
18091
|
+
users: z52.number().optional(),
|
|
17990
18092
|
/** Which GA4 dimension this row came from: session (sessionSource), first_user (firstUserSource), or manual_utm (utm_source parameter) */
|
|
17991
18093
|
sourceDimension: ga4SourceDimensionSchema
|
|
17992
18094
|
});
|
|
17993
|
-
var ga4AiReferralDailySourceSchema =
|
|
17994
|
-
source:
|
|
17995
|
-
sessions:
|
|
17996
|
-
paidSessions:
|
|
17997
|
-
organicSessions:
|
|
17998
|
-
});
|
|
17999
|
-
var ga4AiReferralDailyEntrySchema =
|
|
18000
|
-
date:
|
|
18001
|
-
sessions:
|
|
18002
|
-
paidSessions:
|
|
18003
|
-
organicSessions:
|
|
18095
|
+
var ga4AiReferralDailySourceSchema = z52.object({
|
|
18096
|
+
source: z52.string(),
|
|
18097
|
+
sessions: z52.number(),
|
|
18098
|
+
paidSessions: z52.number(),
|
|
18099
|
+
organicSessions: z52.number()
|
|
18100
|
+
});
|
|
18101
|
+
var ga4AiReferralDailyEntrySchema = z52.object({
|
|
18102
|
+
date: z52.string(),
|
|
18103
|
+
sessions: z52.number(),
|
|
18104
|
+
paidSessions: z52.number(),
|
|
18105
|
+
organicSessions: z52.number(),
|
|
18004
18106
|
/** Per-source split of the day. `sessions` is the sum of these. */
|
|
18005
|
-
bySource:
|
|
18107
|
+
bySource: z52.array(ga4AiReferralDailySourceSchema)
|
|
18108
|
+
});
|
|
18109
|
+
var ga4AiReferralDailyTrendSchema = linearTrendSchema.extend({
|
|
18110
|
+
startDate: z52.string(),
|
|
18111
|
+
endDate: z52.string()
|
|
18006
18112
|
});
|
|
18007
|
-
var ga4AiReferralDailyDtoSchema =
|
|
18113
|
+
var ga4AiReferralDailyDtoSchema = z52.object({
|
|
18008
18114
|
/** Ascending by date. Dates with no AI referrals are absent, not zero-filled. */
|
|
18009
|
-
days:
|
|
18115
|
+
days: z52.array(ga4AiReferralDailyEntrySchema),
|
|
18010
18116
|
/** Sources present in the window, ordered by total sessions descending. */
|
|
18011
|
-
sources:
|
|
18012
|
-
totalSessions:
|
|
18013
|
-
totalPaidSessions:
|
|
18014
|
-
totalOrganicSessions:
|
|
18117
|
+
sources: z52.array(z52.string()),
|
|
18118
|
+
totalSessions: z52.number(),
|
|
18119
|
+
totalPaidSessions: z52.number(),
|
|
18120
|
+
totalOrganicSessions: z52.number(),
|
|
18015
18121
|
/**
|
|
18016
18122
|
* The same days by AI engine: the five largest engines (the unattributed
|
|
18017
18123
|
* group counts as one), then the rest as `other`. Folded from the same
|
|
18018
18124
|
* winner set as `days`, so each day's values add up to that day's sessions.
|
|
18019
18125
|
*/
|
|
18020
|
-
byEngine: stackedDailySeriesSchema
|
|
18021
|
-
|
|
18022
|
-
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
18027
|
-
|
|
18126
|
+
byEngine: stackedDailySeriesSchema,
|
|
18127
|
+
/**
|
|
18128
|
+
* Fitted over the window's complete GA4 days, server side so every consumer
|
|
18129
|
+
* draws the same line. A day counts once GA4 reported the site's daily total
|
|
18130
|
+
* for it, so a date with no AI row is a measured zero; days before the
|
|
18131
|
+
* project's first stored AI row, and the last two UTC days (still filling),
|
|
18132
|
+
* are left out. Null with fewer than two such days. Optional so a newer
|
|
18133
|
+
* client reads an older API.
|
|
18134
|
+
*/
|
|
18135
|
+
trend: ga4AiReferralDailyTrendSchema.nullable().optional()
|
|
18136
|
+
});
|
|
18137
|
+
var ga4SocialReferralHistoryEntrySchema = z52.object({
|
|
18138
|
+
date: z52.string(),
|
|
18139
|
+
source: z52.string(),
|
|
18140
|
+
medium: z52.string(),
|
|
18141
|
+
sessions: z52.number(),
|
|
18142
|
+
users: z52.number(),
|
|
18028
18143
|
/** GA4 default channel group (e.g. 'Organic Social', 'Paid Social') */
|
|
18029
|
-
channelGroup:
|
|
18144
|
+
channelGroup: z52.string()
|
|
18030
18145
|
});
|
|
18031
|
-
var ga4SessionHistoryEntrySchema =
|
|
18032
|
-
date:
|
|
18033
|
-
sessions:
|
|
18034
|
-
organicSessions:
|
|
18146
|
+
var ga4SessionHistoryEntrySchema = z52.object({
|
|
18147
|
+
date: z52.string(),
|
|
18148
|
+
sessions: z52.number(),
|
|
18149
|
+
organicSessions: z52.number(),
|
|
18035
18150
|
/**
|
|
18036
18151
|
* Unique visitors for the day. Deduplicated by GA when `usersSource` is
|
|
18037
18152
|
* `deduplicated`; a landing-page sum (which overcounts multi-page visitors)
|
|
18038
18153
|
* for days synced before per-day totals were captured.
|
|
18039
18154
|
*/
|
|
18040
|
-
users:
|
|
18155
|
+
users: z52.number(),
|
|
18041
18156
|
/**
|
|
18042
18157
|
* How `users` was derived. `deduplicated` matches the GA UI's active users;
|
|
18043
18158
|
* `landing-page-sum` is the legacy overcount kept so historical days still
|
|
18044
18159
|
* render. Never compare the two across a series without saying which is which.
|
|
18045
18160
|
*/
|
|
18046
|
-
usersSource:
|
|
18161
|
+
usersSource: z52.enum(["deduplicated", "landing-page-sum"])
|
|
18047
18162
|
});
|
|
18048
|
-
var gaAcquisitionDimensionSchema =
|
|
18163
|
+
var gaAcquisitionDimensionSchema = z52.enum(["date", "channelGroup", "source", "medium", "hostName", "landingPage"]);
|
|
18049
18164
|
var GaAcquisitionDimensions = gaAcquisitionDimensionSchema.enum;
|
|
18050
|
-
var gaAcquisitionQuerySchema =
|
|
18165
|
+
var gaAcquisitionQuerySchema = z52.object({
|
|
18051
18166
|
window: metricsWindowSchema.optional(),
|
|
18052
|
-
startDate:
|
|
18053
|
-
endDate:
|
|
18054
|
-
channel:
|
|
18055
|
-
source:
|
|
18056
|
-
medium:
|
|
18057
|
-
hostName:
|
|
18058
|
-
landingPage:
|
|
18059
|
-
pathPrefix:
|
|
18060
|
-
groupBy:
|
|
18061
|
-
limit:
|
|
18062
|
-
offset:
|
|
18063
|
-
}).strict();
|
|
18064
|
-
var gaAcquisitionRowSchema =
|
|
18065
|
-
date:
|
|
18066
|
-
channelGroup:
|
|
18067
|
-
source:
|
|
18068
|
-
medium:
|
|
18069
|
-
hostName:
|
|
18070
|
-
landingPage:
|
|
18071
|
-
sessions:
|
|
18072
|
-
});
|
|
18073
|
-
var gaAcquisitionResponseSchema =
|
|
18074
|
-
source:
|
|
18167
|
+
startDate: z52.iso.date().optional(),
|
|
18168
|
+
endDate: z52.iso.date().optional(),
|
|
18169
|
+
channel: z52.string().optional(),
|
|
18170
|
+
source: z52.string().optional(),
|
|
18171
|
+
medium: z52.string().optional(),
|
|
18172
|
+
hostName: z52.string().optional(),
|
|
18173
|
+
landingPage: z52.string().optional(),
|
|
18174
|
+
pathPrefix: z52.string().optional(),
|
|
18175
|
+
groupBy: z52.string().refine((value) => value.split(",").every((key) => gaAcquisitionDimensionSchema.safeParse(key.trim()).success), `groupBy must contain: ${gaAcquisitionDimensionSchema.options.join(", ")}`).optional(),
|
|
18176
|
+
limit: z52.number().int().min(1).max(1e3).optional(),
|
|
18177
|
+
offset: z52.number().int().nonnegative().optional()
|
|
18178
|
+
}).strict();
|
|
18179
|
+
var gaAcquisitionRowSchema = z52.object({
|
|
18180
|
+
date: z52.string().optional(),
|
|
18181
|
+
channelGroup: z52.string().optional(),
|
|
18182
|
+
source: z52.string().optional(),
|
|
18183
|
+
medium: z52.string().optional(),
|
|
18184
|
+
hostName: z52.string().optional(),
|
|
18185
|
+
landingPage: z52.string().optional(),
|
|
18186
|
+
sessions: z52.number().int().nonnegative()
|
|
18187
|
+
});
|
|
18188
|
+
var gaAcquisitionResponseSchema = z52.object({
|
|
18189
|
+
source: z52.literal("ga4-acquisition"),
|
|
18075
18190
|
status: gaMeasurementComponentStatusSchema,
|
|
18076
|
-
error:
|
|
18077
|
-
syncedAt:
|
|
18078
|
-
scope:
|
|
18079
|
-
window:
|
|
18080
|
-
coverage:
|
|
18081
|
-
filters:
|
|
18082
|
-
groupBy:
|
|
18083
|
-
channelGroups:
|
|
18084
|
-
totalSessions:
|
|
18085
|
-
totalRows:
|
|
18086
|
-
limit:
|
|
18087
|
-
offset:
|
|
18088
|
-
rows:
|
|
18191
|
+
error: z52.string().nullable(),
|
|
18192
|
+
syncedAt: z52.string().nullable(),
|
|
18193
|
+
scope: z52.object({ project: z52.string(), attribution: z52.literal("project-only"), unavailableDimensions: z52.array(z52.enum(["property", "target", "market"])) }),
|
|
18194
|
+
window: z52.object({ startDate: z52.string().nullable(), endDate: z52.string().nullable(), window: metricsWindowSchema }),
|
|
18195
|
+
coverage: z52.object({ earliestDate: z52.string().nullable(), latestDate: z52.string().nullable() }),
|
|
18196
|
+
filters: z52.object({ channel: z52.string().nullable(), source: z52.string().nullable(), medium: z52.string().nullable(), hostName: z52.string().nullable(), landingPage: z52.string().nullable(), pathPrefix: z52.string().nullable() }),
|
|
18197
|
+
groupBy: z52.array(gaAcquisitionDimensionSchema),
|
|
18198
|
+
channelGroups: z52.array(z52.string()),
|
|
18199
|
+
totalSessions: z52.number().int().nonnegative(),
|
|
18200
|
+
totalRows: z52.number().int().nonnegative(),
|
|
18201
|
+
limit: z52.number().int(),
|
|
18202
|
+
offset: z52.number().int(),
|
|
18203
|
+
rows: z52.array(gaAcquisitionRowSchema)
|
|
18089
18204
|
});
|
|
18090
18205
|
function formatGaOverviewValue(key, value, options = {}) {
|
|
18091
18206
|
if (value === null) return "\u2014";
|
|
@@ -18168,8 +18283,8 @@ function collectBrandAliasesFromDomain(domain) {
|
|
|
18168
18283
|
}
|
|
18169
18284
|
|
|
18170
18285
|
// ../contracts/src/backlinks.ts
|
|
18171
|
-
import { z as
|
|
18172
|
-
var backlinkSourceSchema =
|
|
18286
|
+
import { z as z53 } from "zod";
|
|
18287
|
+
var backlinkSourceSchema = z53.enum(["commoncrawl", "bing-webmaster"]);
|
|
18173
18288
|
var BacklinkSources = backlinkSourceSchema.enum;
|
|
18174
18289
|
function computeBacklinkSummaryMetrics(rows) {
|
|
18175
18290
|
if (rows.length === 0) {
|
|
@@ -18185,108 +18300,108 @@ function computeBacklinkSummaryMetrics(rows) {
|
|
|
18185
18300
|
top10HostsShare: share.toFixed(6)
|
|
18186
18301
|
};
|
|
18187
18302
|
}
|
|
18188
|
-
var ccReleaseSyncStatusSchema =
|
|
18303
|
+
var ccReleaseSyncStatusSchema = z53.enum(["queued", "downloading", "querying", "ready", "failed"]);
|
|
18189
18304
|
var CcReleaseSyncStatuses = ccReleaseSyncStatusSchema.enum;
|
|
18190
|
-
var ccReleaseSyncDtoSchema =
|
|
18191
|
-
id:
|
|
18192
|
-
release:
|
|
18305
|
+
var ccReleaseSyncDtoSchema = z53.object({
|
|
18306
|
+
id: z53.string(),
|
|
18307
|
+
release: z53.string(),
|
|
18193
18308
|
status: ccReleaseSyncStatusSchema,
|
|
18194
|
-
phaseDetail:
|
|
18195
|
-
vertexPath:
|
|
18196
|
-
edgesPath:
|
|
18197
|
-
vertexSha256:
|
|
18198
|
-
edgesSha256:
|
|
18199
|
-
vertexBytes:
|
|
18200
|
-
edgesBytes:
|
|
18201
|
-
projectsProcessed:
|
|
18202
|
-
domainsDiscovered:
|
|
18203
|
-
downloadStartedAt:
|
|
18204
|
-
downloadFinishedAt:
|
|
18205
|
-
queryStartedAt:
|
|
18206
|
-
queryFinishedAt:
|
|
18207
|
-
error:
|
|
18208
|
-
createdAt:
|
|
18209
|
-
updatedAt:
|
|
18309
|
+
phaseDetail: z53.string().nullable().optional(),
|
|
18310
|
+
vertexPath: z53.string().nullable().optional(),
|
|
18311
|
+
edgesPath: z53.string().nullable().optional(),
|
|
18312
|
+
vertexSha256: z53.string().nullable().optional(),
|
|
18313
|
+
edgesSha256: z53.string().nullable().optional(),
|
|
18314
|
+
vertexBytes: z53.number().int().nullable().optional(),
|
|
18315
|
+
edgesBytes: z53.number().int().nullable().optional(),
|
|
18316
|
+
projectsProcessed: z53.number().int().nullable().optional(),
|
|
18317
|
+
domainsDiscovered: z53.number().int().nullable().optional(),
|
|
18318
|
+
downloadStartedAt: z53.string().nullable().optional(),
|
|
18319
|
+
downloadFinishedAt: z53.string().nullable().optional(),
|
|
18320
|
+
queryStartedAt: z53.string().nullable().optional(),
|
|
18321
|
+
queryFinishedAt: z53.string().nullable().optional(),
|
|
18322
|
+
error: z53.string().nullable().optional(),
|
|
18323
|
+
createdAt: z53.string(),
|
|
18324
|
+
updatedAt: z53.string()
|
|
18210
18325
|
});
|
|
18211
|
-
var backlinkDomainDtoSchema =
|
|
18212
|
-
linkingDomain:
|
|
18213
|
-
numHosts:
|
|
18326
|
+
var backlinkDomainDtoSchema = z53.object({
|
|
18327
|
+
linkingDomain: z53.string(),
|
|
18328
|
+
numHosts: z53.number().int(),
|
|
18214
18329
|
source: backlinkSourceSchema
|
|
18215
18330
|
});
|
|
18216
|
-
var backlinkSummaryDtoSchema =
|
|
18217
|
-
projectId:
|
|
18218
|
-
release:
|
|
18219
|
-
targetDomain:
|
|
18220
|
-
totalLinkingDomains:
|
|
18221
|
-
totalHosts:
|
|
18222
|
-
top10HostsShare:
|
|
18223
|
-
queriedAt:
|
|
18331
|
+
var backlinkSummaryDtoSchema = z53.object({
|
|
18332
|
+
projectId: z53.string(),
|
|
18333
|
+
release: z53.string(),
|
|
18334
|
+
targetDomain: z53.string(),
|
|
18335
|
+
totalLinkingDomains: z53.number().int(),
|
|
18336
|
+
totalHosts: z53.number().int(),
|
|
18337
|
+
top10HostsShare: z53.string(),
|
|
18338
|
+
queriedAt: z53.string(),
|
|
18224
18339
|
source: backlinkSourceSchema,
|
|
18225
18340
|
// Populated when the response is filtered (e.g. ?excludeCrawlers=1).
|
|
18226
18341
|
// Counts the rows omitted from totalLinkingDomains/totalHosts so callers
|
|
18227
18342
|
// can show "N hidden" hints without re-deriving them.
|
|
18228
|
-
excludedLinkingDomains:
|
|
18229
|
-
excludedHosts:
|
|
18343
|
+
excludedLinkingDomains: z53.number().int().optional(),
|
|
18344
|
+
excludedHosts: z53.number().int().optional()
|
|
18230
18345
|
});
|
|
18231
|
-
var backlinkListResponseSchema =
|
|
18346
|
+
var backlinkListResponseSchema = z53.object({
|
|
18232
18347
|
source: backlinkSourceSchema,
|
|
18233
18348
|
summary: backlinkSummaryDtoSchema.nullable(),
|
|
18234
|
-
total:
|
|
18235
|
-
rows:
|
|
18236
|
-
});
|
|
18237
|
-
var backlinkHistoryEntrySchema =
|
|
18238
|
-
release:
|
|
18239
|
-
totalLinkingDomains:
|
|
18240
|
-
totalHosts:
|
|
18241
|
-
top10HostsShare:
|
|
18242
|
-
queriedAt:
|
|
18349
|
+
total: z53.number().int(),
|
|
18350
|
+
rows: z53.array(backlinkDomainDtoSchema)
|
|
18351
|
+
});
|
|
18352
|
+
var backlinkHistoryEntrySchema = z53.object({
|
|
18353
|
+
release: z53.string(),
|
|
18354
|
+
totalLinkingDomains: z53.number().int(),
|
|
18355
|
+
totalHosts: z53.number().int(),
|
|
18356
|
+
top10HostsShare: z53.string(),
|
|
18357
|
+
queriedAt: z53.string(),
|
|
18243
18358
|
source: backlinkSourceSchema
|
|
18244
18359
|
});
|
|
18245
|
-
var backlinkSourceAvailabilityDtoSchema =
|
|
18360
|
+
var backlinkSourceAvailabilityDtoSchema = z53.object({
|
|
18246
18361
|
source: backlinkSourceSchema,
|
|
18247
|
-
connected:
|
|
18248
|
-
hasData:
|
|
18249
|
-
latestRelease:
|
|
18250
|
-
totalLinkingDomains:
|
|
18251
|
-
lastSyncedAt:
|
|
18252
|
-
});
|
|
18253
|
-
var backlinkSourcesResponseSchema =
|
|
18254
|
-
projectId:
|
|
18255
|
-
targetDomain:
|
|
18256
|
-
sources:
|
|
18257
|
-
anyConnected:
|
|
18258
|
-
anyData:
|
|
18259
|
-
});
|
|
18260
|
-
var backlinksInstallStatusDtoSchema =
|
|
18261
|
-
duckdbInstalled:
|
|
18262
|
-
duckdbVersion:
|
|
18263
|
-
duckdbSpec:
|
|
18264
|
-
pluginDir:
|
|
18265
|
-
});
|
|
18266
|
-
var backlinksInstallResultDtoSchema =
|
|
18267
|
-
installed:
|
|
18268
|
-
version:
|
|
18269
|
-
path:
|
|
18270
|
-
alreadyPresent:
|
|
18271
|
-
});
|
|
18272
|
-
var ccAvailableReleaseSchema =
|
|
18273
|
-
release:
|
|
18274
|
-
vertexUrl:
|
|
18275
|
-
edgesUrl:
|
|
18276
|
-
vertexBytes:
|
|
18277
|
-
edgesBytes:
|
|
18278
|
-
lastModified:
|
|
18279
|
-
});
|
|
18280
|
-
var ccCachedReleaseSchema =
|
|
18281
|
-
release:
|
|
18362
|
+
connected: z53.boolean(),
|
|
18363
|
+
hasData: z53.boolean(),
|
|
18364
|
+
latestRelease: z53.string().nullable(),
|
|
18365
|
+
totalLinkingDomains: z53.number().int(),
|
|
18366
|
+
lastSyncedAt: z53.string().nullable()
|
|
18367
|
+
});
|
|
18368
|
+
var backlinkSourcesResponseSchema = z53.object({
|
|
18369
|
+
projectId: z53.string(),
|
|
18370
|
+
targetDomain: z53.string(),
|
|
18371
|
+
sources: z53.array(backlinkSourceAvailabilityDtoSchema),
|
|
18372
|
+
anyConnected: z53.boolean(),
|
|
18373
|
+
anyData: z53.boolean()
|
|
18374
|
+
});
|
|
18375
|
+
var backlinksInstallStatusDtoSchema = z53.object({
|
|
18376
|
+
duckdbInstalled: z53.boolean(),
|
|
18377
|
+
duckdbVersion: z53.string().nullable().optional(),
|
|
18378
|
+
duckdbSpec: z53.string(),
|
|
18379
|
+
pluginDir: z53.string()
|
|
18380
|
+
});
|
|
18381
|
+
var backlinksInstallResultDtoSchema = z53.object({
|
|
18382
|
+
installed: z53.boolean(),
|
|
18383
|
+
version: z53.string(),
|
|
18384
|
+
path: z53.string(),
|
|
18385
|
+
alreadyPresent: z53.boolean()
|
|
18386
|
+
});
|
|
18387
|
+
var ccAvailableReleaseSchema = z53.object({
|
|
18388
|
+
release: z53.string(),
|
|
18389
|
+
vertexUrl: z53.string(),
|
|
18390
|
+
edgesUrl: z53.string(),
|
|
18391
|
+
vertexBytes: z53.number().int().nullable(),
|
|
18392
|
+
edgesBytes: z53.number().int().nullable(),
|
|
18393
|
+
lastModified: z53.string().nullable()
|
|
18394
|
+
});
|
|
18395
|
+
var ccCachedReleaseSchema = z53.object({
|
|
18396
|
+
release: z53.string(),
|
|
18282
18397
|
syncStatus: ccReleaseSyncStatusSchema.nullable(),
|
|
18283
|
-
bytes:
|
|
18284
|
-
lastUsedAt:
|
|
18398
|
+
bytes: z53.number().int(),
|
|
18399
|
+
lastUsedAt: z53.string().nullable()
|
|
18285
18400
|
});
|
|
18286
18401
|
|
|
18287
18402
|
// ../contracts/src/content.ts
|
|
18288
|
-
import { z as
|
|
18289
|
-
var contentActionSchema =
|
|
18403
|
+
import { z as z54 } from "zod";
|
|
18404
|
+
var contentActionSchema = z54.enum(["create", "expand", "refresh", "add-schema"]);
|
|
18290
18405
|
var ContentActions = contentActionSchema.enum;
|
|
18291
18406
|
function contentActionLabel(action) {
|
|
18292
18407
|
switch (action) {
|
|
@@ -18300,9 +18415,9 @@ function contentActionLabel(action) {
|
|
|
18300
18415
|
return "Add schema";
|
|
18301
18416
|
}
|
|
18302
18417
|
}
|
|
18303
|
-
var demandSourceSchema =
|
|
18418
|
+
var demandSourceSchema = z54.enum(["gsc", "competitor-evidence", "both"]);
|
|
18304
18419
|
var DemandSources = demandSourceSchema.enum;
|
|
18305
|
-
var actionConfidenceSchema =
|
|
18420
|
+
var actionConfidenceSchema = z54.enum(["high", "medium", "low"]);
|
|
18306
18421
|
var ActionConfidences = actionConfidenceSchema.enum;
|
|
18307
18422
|
function actionConfidenceLabel(confidence) {
|
|
18308
18423
|
switch (confidence) {
|
|
@@ -18314,7 +18429,7 @@ function actionConfidenceLabel(confidence) {
|
|
|
18314
18429
|
return "Low";
|
|
18315
18430
|
}
|
|
18316
18431
|
}
|
|
18317
|
-
var pageTypeSchema =
|
|
18432
|
+
var pageTypeSchema = z54.enum([
|
|
18318
18433
|
"blog-post",
|
|
18319
18434
|
"comparison",
|
|
18320
18435
|
"listicle",
|
|
@@ -18323,7 +18438,7 @@ var pageTypeSchema = z53.enum([
|
|
|
18323
18438
|
"glossary"
|
|
18324
18439
|
]);
|
|
18325
18440
|
var PageTypes = pageTypeSchema.enum;
|
|
18326
|
-
var contentActionStateSchema =
|
|
18441
|
+
var contentActionStateSchema = z54.enum([
|
|
18327
18442
|
"proposed",
|
|
18328
18443
|
"briefed",
|
|
18329
18444
|
"payload-generated",
|
|
@@ -18333,7 +18448,7 @@ var contentActionStateSchema = z53.enum([
|
|
|
18333
18448
|
"dismissed"
|
|
18334
18449
|
]);
|
|
18335
18450
|
var ContentActionStates = contentActionStateSchema.enum;
|
|
18336
|
-
var winnabilityClassSchema =
|
|
18451
|
+
var winnabilityClassSchema = z54.enum(["ownable", "ceded"]);
|
|
18337
18452
|
var WinnabilityClasses = winnabilityClassSchema.enum;
|
|
18338
18453
|
function winnabilityClassLabel(winnabilityClass) {
|
|
18339
18454
|
switch (winnabilityClass) {
|
|
@@ -18368,40 +18483,40 @@ function deriveWinnabilityClass(citedSurfaceDomains, surfaceClasses, threshold =
|
|
|
18368
18483
|
winnability
|
|
18369
18484
|
};
|
|
18370
18485
|
}
|
|
18371
|
-
var ourBestPageSchema =
|
|
18372
|
-
url:
|
|
18373
|
-
gscImpressions:
|
|
18374
|
-
gscClicks:
|
|
18486
|
+
var ourBestPageSchema = z54.object({
|
|
18487
|
+
url: z54.string(),
|
|
18488
|
+
gscImpressions: z54.number().nonnegative(),
|
|
18489
|
+
gscClicks: z54.number().nonnegative(),
|
|
18375
18490
|
// Null when the page came from the inventory fallback (no GSC ranking data).
|
|
18376
|
-
gscAvgPosition:
|
|
18377
|
-
organicSessions:
|
|
18378
|
-
});
|
|
18379
|
-
var winningCompetitorSchema =
|
|
18380
|
-
domain:
|
|
18381
|
-
url:
|
|
18382
|
-
title:
|
|
18383
|
-
citationCount:
|
|
18384
|
-
});
|
|
18385
|
-
var scoreBreakdownSchema =
|
|
18386
|
-
demand:
|
|
18387
|
-
competitor:
|
|
18388
|
-
absence:
|
|
18389
|
-
gapSeverity:
|
|
18390
|
-
});
|
|
18391
|
-
var existingActionRefSchema =
|
|
18392
|
-
actionId:
|
|
18491
|
+
gscAvgPosition: z54.number().nonnegative().nullable(),
|
|
18492
|
+
organicSessions: z54.number().nonnegative()
|
|
18493
|
+
});
|
|
18494
|
+
var winningCompetitorSchema = z54.object({
|
|
18495
|
+
domain: z54.string(),
|
|
18496
|
+
url: z54.string(),
|
|
18497
|
+
title: z54.string(),
|
|
18498
|
+
citationCount: z54.number().int().nonnegative()
|
|
18499
|
+
});
|
|
18500
|
+
var scoreBreakdownSchema = z54.object({
|
|
18501
|
+
demand: z54.number(),
|
|
18502
|
+
competitor: z54.number(),
|
|
18503
|
+
absence: z54.number(),
|
|
18504
|
+
gapSeverity: z54.number()
|
|
18505
|
+
});
|
|
18506
|
+
var existingActionRefSchema = z54.object({
|
|
18507
|
+
actionId: z54.string(),
|
|
18393
18508
|
state: contentActionStateSchema,
|
|
18394
|
-
lastUpdated:
|
|
18509
|
+
lastUpdated: z54.string()
|
|
18395
18510
|
});
|
|
18396
|
-
var contentTargetRowDtoSchema =
|
|
18397
|
-
targetRef:
|
|
18398
|
-
query:
|
|
18511
|
+
var contentTargetRowDtoSchema = z54.object({
|
|
18512
|
+
targetRef: z54.string(),
|
|
18513
|
+
query: z54.string(),
|
|
18399
18514
|
action: contentActionSchema,
|
|
18400
18515
|
ourBestPage: ourBestPageSchema.nullable(),
|
|
18401
18516
|
winningCompetitor: winningCompetitorSchema.nullable(),
|
|
18402
|
-
score:
|
|
18517
|
+
score: z54.number(),
|
|
18403
18518
|
scoreBreakdown: scoreBreakdownSchema,
|
|
18404
|
-
drivers:
|
|
18519
|
+
drivers: z54.array(z54.string()),
|
|
18405
18520
|
demandSource: demandSourceSchema,
|
|
18406
18521
|
actionConfidence: actionConfidenceSchema,
|
|
18407
18522
|
existingAction: existingActionRefSchema.nullable(),
|
|
@@ -18416,134 +18531,134 @@ var contentTargetRowDtoSchema = z53.object({
|
|
|
18416
18531
|
* `[0, 1]`. `null` when the gate failed open (no classification coverage for
|
|
18417
18532
|
* the cited surface) — distinct from a computed `1.0`.
|
|
18418
18533
|
*/
|
|
18419
|
-
winnability: fraction(
|
|
18420
|
-
});
|
|
18421
|
-
var contentTargetsResponseDtoSchema =
|
|
18422
|
-
targets:
|
|
18423
|
-
contextMetrics:
|
|
18424
|
-
totalAiReferralSessions:
|
|
18425
|
-
latestRunId:
|
|
18426
|
-
runTimestamp:
|
|
18534
|
+
winnability: fraction(z54.number().min(0).max(1)).nullable()
|
|
18535
|
+
});
|
|
18536
|
+
var contentTargetsResponseDtoSchema = z54.object({
|
|
18537
|
+
targets: z54.array(contentTargetRowDtoSchema),
|
|
18538
|
+
contextMetrics: z54.object({
|
|
18539
|
+
totalAiReferralSessions: z54.number().int().nonnegative(),
|
|
18540
|
+
latestRunId: z54.string(),
|
|
18541
|
+
runTimestamp: z54.string()
|
|
18427
18542
|
})
|
|
18428
18543
|
});
|
|
18429
|
-
var contentTargetDismissalDtoSchema =
|
|
18430
|
-
targetRef:
|
|
18431
|
-
addressedUrl:
|
|
18432
|
-
note:
|
|
18433
|
-
dismissedAt:
|
|
18544
|
+
var contentTargetDismissalDtoSchema = z54.object({
|
|
18545
|
+
targetRef: z54.string(),
|
|
18546
|
+
addressedUrl: z54.string().nullable(),
|
|
18547
|
+
note: z54.string().nullable(),
|
|
18548
|
+
dismissedAt: z54.string()
|
|
18434
18549
|
});
|
|
18435
|
-
var contentTargetDismissalsResponseDtoSchema =
|
|
18436
|
-
dismissals:
|
|
18550
|
+
var contentTargetDismissalsResponseDtoSchema = z54.object({
|
|
18551
|
+
dismissals: z54.array(contentTargetDismissalDtoSchema)
|
|
18437
18552
|
});
|
|
18438
|
-
var contentTargetDismissRequestSchema =
|
|
18439
|
-
targetRef:
|
|
18553
|
+
var contentTargetDismissRequestSchema = z54.object({
|
|
18554
|
+
targetRef: z54.string().min(1),
|
|
18440
18555
|
/** URL of the page the user wrote that addresses this recommendation. Stored verbatim for the audit trail; not currently used to suppress the slug-token matcher. */
|
|
18441
|
-
addressedUrl:
|
|
18556
|
+
addressedUrl: z54.string().url().optional(),
|
|
18442
18557
|
/** Free-form note (e.g. "covered in our Q1 content sprint"). 500 char cap is the API surface limit; the DB column is unbounded. */
|
|
18443
|
-
note:
|
|
18558
|
+
note: z54.string().max(500).optional()
|
|
18444
18559
|
});
|
|
18445
|
-
var recommendationExplanationDtoSchema =
|
|
18446
|
-
targetRef:
|
|
18560
|
+
var recommendationExplanationDtoSchema = z54.object({
|
|
18561
|
+
targetRef: z54.string(),
|
|
18447
18562
|
/** Version of the prompt template used. Bumping the version invalidates the cache forward without touching the table. */
|
|
18448
|
-
promptVersion:
|
|
18563
|
+
promptVersion: z54.string(),
|
|
18449
18564
|
/** Provider that produced the explanation (e.g. "claude", "gemini"). */
|
|
18450
|
-
provider:
|
|
18565
|
+
provider: z54.string(),
|
|
18451
18566
|
/** Model id within that provider (e.g. "claude-sonnet-4-6"). */
|
|
18452
|
-
model:
|
|
18567
|
+
model: z54.string(),
|
|
18453
18568
|
/** Markdown-formatted rationale + recommended next steps. */
|
|
18454
|
-
responseText:
|
|
18569
|
+
responseText: z54.string(),
|
|
18455
18570
|
/** Estimated cost in millicents (1/100 of a cent). 0 when unknown. */
|
|
18456
|
-
costMillicents:
|
|
18457
|
-
generatedAt:
|
|
18571
|
+
costMillicents: z54.number().int().nonnegative(),
|
|
18572
|
+
generatedAt: z54.string()
|
|
18458
18573
|
});
|
|
18459
|
-
var recommendationExplainRequestSchema =
|
|
18574
|
+
var recommendationExplainRequestSchema = z54.object({
|
|
18460
18575
|
/**
|
|
18461
18576
|
* Optional provider override (e.g. "claude" to force Claude even if
|
|
18462
18577
|
* the project's default is Gemini). Falls through to project default
|
|
18463
18578
|
* → auto-detect when omitted.
|
|
18464
18579
|
*/
|
|
18465
|
-
provider:
|
|
18580
|
+
provider: z54.string().optional(),
|
|
18466
18581
|
/**
|
|
18467
18582
|
* Optional model override within the chosen provider. Falls through to
|
|
18468
18583
|
* the `analyze`-tier default model when omitted.
|
|
18469
18584
|
*/
|
|
18470
|
-
model:
|
|
18585
|
+
model: z54.string().optional(),
|
|
18471
18586
|
/**
|
|
18472
18587
|
* Force a fresh LLM call even if a cached explanation exists for the
|
|
18473
18588
|
* current prompt version. Use sparingly — defeats the cache.
|
|
18474
18589
|
*/
|
|
18475
|
-
forceRefresh:
|
|
18590
|
+
forceRefresh: z54.boolean().optional()
|
|
18476
18591
|
});
|
|
18477
|
-
var contentBriefDtoSchema =
|
|
18592
|
+
var contentBriefDtoSchema = z54.object({
|
|
18478
18593
|
/** The query the brief is for (echoed from the recommendation). */
|
|
18479
|
-
targetQuery:
|
|
18594
|
+
targetQuery: z54.string().trim().min(1),
|
|
18480
18595
|
/** Always `ownable` in practice — the gate rejects `ceded` before synthesis. */
|
|
18481
18596
|
winnabilityClass: winnabilityClassSchema,
|
|
18482
18597
|
/** The differentiated content angle to take. */
|
|
18483
|
-
angle:
|
|
18598
|
+
angle: z54.string().trim().min(1),
|
|
18484
18599
|
/** Why this query is winnable, citing the cited-surface signal. */
|
|
18485
|
-
whyWinnable:
|
|
18600
|
+
whyWinnable: z54.string().trim().min(1),
|
|
18486
18601
|
/** The schema.org type or markup to add or extend. */
|
|
18487
|
-
schemaHookup:
|
|
18602
|
+
schemaHookup: z54.string().trim().min(1),
|
|
18488
18603
|
/** Why the cited surface is controllable (the ownable-vs-ceded reasoning). */
|
|
18489
|
-
controllableSurfaceRationale:
|
|
18604
|
+
controllableSurfaceRationale: z54.string().trim().min(1)
|
|
18490
18605
|
});
|
|
18491
|
-
var recommendationBriefDtoSchema =
|
|
18492
|
-
targetRef:
|
|
18606
|
+
var recommendationBriefDtoSchema = z54.object({
|
|
18607
|
+
targetRef: z54.string(),
|
|
18493
18608
|
/** Version of the brief prompt template; bumping invalidates the cache forward. */
|
|
18494
|
-
promptVersion:
|
|
18495
|
-
provider:
|
|
18496
|
-
model:
|
|
18609
|
+
promptVersion: z54.string(),
|
|
18610
|
+
provider: z54.string(),
|
|
18611
|
+
model: z54.string(),
|
|
18497
18612
|
brief: contentBriefDtoSchema,
|
|
18498
18613
|
/** Estimated cost in millicents (1/100 of a cent). 0 when unknown. */
|
|
18499
|
-
costMillicents:
|
|
18500
|
-
generatedAt:
|
|
18614
|
+
costMillicents: z54.number().int().nonnegative(),
|
|
18615
|
+
generatedAt: z54.string()
|
|
18501
18616
|
});
|
|
18502
|
-
var domainClassificationDtoSchema =
|
|
18503
|
-
domain:
|
|
18617
|
+
var domainClassificationDtoSchema = z54.object({
|
|
18618
|
+
domain: z54.string(),
|
|
18504
18619
|
competitorType: discoveryCompetitorTypeSchema,
|
|
18505
|
-
hits:
|
|
18506
|
-
updatedAt:
|
|
18620
|
+
hits: z54.number().int().nonnegative(),
|
|
18621
|
+
updatedAt: z54.string()
|
|
18622
|
+
});
|
|
18623
|
+
var domainClassificationsResponseDtoSchema = z54.object({
|
|
18624
|
+
classifications: z54.array(domainClassificationDtoSchema)
|
|
18507
18625
|
});
|
|
18508
|
-
var
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
|
|
18515
|
-
|
|
18516
|
-
|
|
18517
|
-
|
|
18518
|
-
|
|
18519
|
-
|
|
18520
|
-
|
|
18521
|
-
|
|
18522
|
-
|
|
18523
|
-
|
|
18524
|
-
|
|
18525
|
-
|
|
18526
|
-
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
|
|
18530
|
-
|
|
18531
|
-
|
|
18532
|
-
|
|
18533
|
-
|
|
18534
|
-
|
|
18535
|
-
var contentGapsResponseDtoSchema = z53.object({
|
|
18536
|
-
gaps: z53.array(contentGapRowDtoSchema),
|
|
18537
|
-
latestRunId: z53.string()
|
|
18626
|
+
var contentGroundingSourceSchema = z54.object({
|
|
18627
|
+
uri: z54.string(),
|
|
18628
|
+
title: z54.string(),
|
|
18629
|
+
domain: z54.string(),
|
|
18630
|
+
isOurDomain: z54.boolean(),
|
|
18631
|
+
isCompetitor: z54.boolean(),
|
|
18632
|
+
citationCount: z54.number().int().nonnegative(),
|
|
18633
|
+
providers: z54.array(providerNameSchema)
|
|
18634
|
+
});
|
|
18635
|
+
var contentSourceRowDtoSchema = z54.object({
|
|
18636
|
+
query: z54.string(),
|
|
18637
|
+
groundingSources: z54.array(contentGroundingSourceSchema)
|
|
18638
|
+
});
|
|
18639
|
+
var contentSourcesResponseDtoSchema = z54.object({
|
|
18640
|
+
sources: z54.array(contentSourceRowDtoSchema),
|
|
18641
|
+
latestRunId: z54.string()
|
|
18642
|
+
});
|
|
18643
|
+
var contentGapRowDtoSchema = z54.object({
|
|
18644
|
+
query: z54.string(),
|
|
18645
|
+
competitorDomains: z54.array(z54.string()),
|
|
18646
|
+
competitorCount: z54.number().int().nonnegative(),
|
|
18647
|
+
missRate: fraction(z54.number().min(0).max(1)),
|
|
18648
|
+
lastSeenInRunId: z54.string()
|
|
18649
|
+
});
|
|
18650
|
+
var contentGapsResponseDtoSchema = z54.object({
|
|
18651
|
+
gaps: z54.array(contentGapRowDtoSchema),
|
|
18652
|
+
latestRunId: z54.string()
|
|
18538
18653
|
});
|
|
18539
18654
|
|
|
18540
18655
|
// ../contracts/src/doctor.ts
|
|
18541
|
-
import { z as
|
|
18542
|
-
var checkStatusSchema =
|
|
18656
|
+
import { z as z55 } from "zod";
|
|
18657
|
+
var checkStatusSchema = z55.enum(["ok", "warn", "fail", "skipped"]);
|
|
18543
18658
|
var CheckStatuses = checkStatusSchema.enum;
|
|
18544
|
-
var checkScopeSchema =
|
|
18659
|
+
var checkScopeSchema = z55.enum(["global", "project"]);
|
|
18545
18660
|
var CheckScopes = checkScopeSchema.enum;
|
|
18546
|
-
var checkCategorySchema =
|
|
18661
|
+
var checkCategorySchema = z55.enum([
|
|
18547
18662
|
"auth",
|
|
18548
18663
|
"config",
|
|
18549
18664
|
"providers",
|
|
@@ -18555,9 +18670,9 @@ var checkCategorySchema = z54.enum([
|
|
|
18555
18670
|
]);
|
|
18556
18671
|
var CheckCategories = checkCategorySchema.enum;
|
|
18557
18672
|
var CHECK_RUNTIME_ERROR_SUFFIX = ".runtime-error";
|
|
18558
|
-
var checkNotificationPolicySchema =
|
|
18673
|
+
var checkNotificationPolicySchema = z55.enum(["health", "silent"]);
|
|
18559
18674
|
var CheckNotificationPolicies = checkNotificationPolicySchema.enum;
|
|
18560
|
-
var reportMonthSchema =
|
|
18675
|
+
var reportMonthSchema = z55.string().regex(/^[1-9]\d{3}-(0[1-9]|1[0-2])$/, "Expected YYYY-MM");
|
|
18561
18676
|
function reportMonthsForDoctor(reportMonth, now = /* @__PURE__ */ new Date()) {
|
|
18562
18677
|
if (reportMonth !== void 0) return [reportMonthSchema.parse(reportMonth)];
|
|
18563
18678
|
const current = now.toISOString().slice(0, 7);
|
|
@@ -18569,40 +18684,40 @@ function gradedReportMonths(months, now = /* @__PURE__ */ new Date()) {
|
|
|
18569
18684
|
const current = now.toISOString().slice(0, 7);
|
|
18570
18685
|
return new Set(months.length > 1 ? months.filter((month) => month !== current) : months);
|
|
18571
18686
|
}
|
|
18572
|
-
var healthAlertCopySchema =
|
|
18573
|
-
label:
|
|
18574
|
-
line:
|
|
18575
|
-
next:
|
|
18687
|
+
var healthAlertCopySchema = z55.object({
|
|
18688
|
+
label: z55.string().describe(`The problem in a few words, e.g. "Can't reach Google".`),
|
|
18689
|
+
line: z55.string().describe("What happened, in one plain sentence."),
|
|
18690
|
+
next: z55.string().nullable().describe("What to do, in one plain sentence; null when nothing needs doing yet.")
|
|
18576
18691
|
});
|
|
18577
|
-
var checkResultSchema =
|
|
18578
|
-
id:
|
|
18692
|
+
var checkResultSchema = z55.object({
|
|
18693
|
+
id: z55.string(),
|
|
18579
18694
|
category: checkCategorySchema,
|
|
18580
18695
|
scope: checkScopeSchema,
|
|
18581
|
-
title:
|
|
18696
|
+
title: z55.string(),
|
|
18582
18697
|
status: checkStatusSchema,
|
|
18583
18698
|
notificationPolicy: checkNotificationPolicySchema.optional().describe("Health checks page by default. Silent checks (report advisories and standing advisories) remain visible but never affect health alert state."),
|
|
18584
|
-
code:
|
|
18585
|
-
urgent:
|
|
18586
|
-
summary:
|
|
18587
|
-
remediation:
|
|
18588
|
-
details:
|
|
18699
|
+
code: z55.string().describe('Stable machine-readable code (e.g. "google.token.refresh-failed"). Use this for filtering and remediation logic.'),
|
|
18700
|
+
urgent: z55.boolean().optional().describe('True when this result is a problem a person has to act on now (the website is down, daily data stopped arriving, a sync keeps failing). Urgent results are what the health.urgent notification event reports. A result set aside under its failing cause (status "skipped", code "<id>.superseded") keeps the flag: the problem is still open.'),
|
|
18701
|
+
summary: z55.string(),
|
|
18702
|
+
remediation: z55.string().nullable().optional().describe('Operator-facing next step. Null when status is "ok" or no specific remediation applies.'),
|
|
18703
|
+
details: z55.record(z55.string(), z55.unknown()).optional().describe("Structured context \u2014 principal email, redirect URI, missing scopes, etc. Stable per check id."),
|
|
18589
18704
|
alert: healthAlertCopySchema.optional().describe("Plain words a health alert shows for this result. Absent when the check has none; alerts then fall back to the summary."),
|
|
18590
|
-
durationMs:
|
|
18705
|
+
durationMs: z55.number().int().nonnegative().describe("How long the check took to execute.")
|
|
18591
18706
|
});
|
|
18592
|
-
var doctorReportSchema =
|
|
18707
|
+
var doctorReportSchema = z55.object({
|
|
18593
18708
|
scope: checkScopeSchema,
|
|
18594
|
-
project:
|
|
18595
|
-
reportMonths:
|
|
18596
|
-
generatedAt:
|
|
18597
|
-
durationMs:
|
|
18598
|
-
summary:
|
|
18599
|
-
total:
|
|
18600
|
-
ok:
|
|
18601
|
-
warn:
|
|
18602
|
-
fail:
|
|
18603
|
-
skipped:
|
|
18709
|
+
project: z55.string().nullable().describe('Project name when scope is "project", null otherwise.'),
|
|
18710
|
+
reportMonths: z55.array(reportMonthSchema).optional().describe("Calendar months evaluated by project report readiness checks."),
|
|
18711
|
+
generatedAt: z55.string().describe("ISO-8601 timestamp when this doctor run started."),
|
|
18712
|
+
durationMs: z55.number().int().nonnegative(),
|
|
18713
|
+
summary: z55.object({
|
|
18714
|
+
total: z55.number().int().nonnegative(),
|
|
18715
|
+
ok: z55.number().int().nonnegative(),
|
|
18716
|
+
warn: z55.number().int().nonnegative(),
|
|
18717
|
+
fail: z55.number().int().nonnegative(),
|
|
18718
|
+
skipped: z55.number().int().nonnegative()
|
|
18604
18719
|
}),
|
|
18605
|
-
checks:
|
|
18720
|
+
checks: z55.array(checkResultSchema)
|
|
18606
18721
|
});
|
|
18607
18722
|
function summarizeCheckResults(results) {
|
|
18608
18723
|
const summary = { total: results.length, ok: 0, warn: 0, fail: 0, skipped: 0 };
|
|
@@ -18635,8 +18750,8 @@ function groupIsoDateRanges(dates) {
|
|
|
18635
18750
|
}
|
|
18636
18751
|
|
|
18637
18752
|
// ../contracts/src/skills.ts
|
|
18638
|
-
import { z as
|
|
18639
|
-
var codingAgentSchema =
|
|
18753
|
+
import { z as z56 } from "zod";
|
|
18754
|
+
var codingAgentSchema = z56.enum(["claude", "codex"]);
|
|
18640
18755
|
var CodingAgents = codingAgentSchema.enum;
|
|
18641
18756
|
function agentPluginClientLabel(client) {
|
|
18642
18757
|
return client === "claude-code" ? "Claude Code" : "Codex";
|
|
@@ -18660,7 +18775,7 @@ function formatCanonryPluginUpdateHint(clients) {
|
|
|
18660
18775
|
if (names.length === 1) return `Update or reinstall \`canonry@canonry\` in ${names[0]}.`;
|
|
18661
18776
|
return `Update or reinstall \`canonry@canonry\` in ${joinPluginSubjects(names)}.`;
|
|
18662
18777
|
}
|
|
18663
|
-
var skillsClientSchema =
|
|
18778
|
+
var skillsClientSchema = z56.enum(["claude", "codex", "all"]);
|
|
18664
18779
|
var SkillsClients = skillsClientSchema.enum;
|
|
18665
18780
|
var SKILL_MANIFEST_FILENAME = ".canonry-skill-manifest.json";
|
|
18666
18781
|
function classifySkillFile(params) {
|
|
@@ -18677,108 +18792,6 @@ function coerceSkillManifest(parsed) {
|
|
|
18677
18792
|
return null;
|
|
18678
18793
|
}
|
|
18679
18794
|
|
|
18680
|
-
// ../contracts/src/statistics.ts
|
|
18681
|
-
import { z as z56 } from "zod";
|
|
18682
|
-
function round(value, dp = 4) {
|
|
18683
|
-
const f = 10 ** dp;
|
|
18684
|
-
return (Math.round(value * f) + 0) / f;
|
|
18685
|
-
}
|
|
18686
|
-
function roundSignificant(value, sig = 6) {
|
|
18687
|
-
if (!Number.isFinite(value) || value === 0) return 0;
|
|
18688
|
-
const magnitude = Math.ceil(Math.log10(Math.abs(value)));
|
|
18689
|
-
const factor = 10 ** (sig - magnitude);
|
|
18690
|
-
return (Math.round(value * factor) + 0) / factor;
|
|
18691
|
-
}
|
|
18692
|
-
function shareOf(part, total) {
|
|
18693
|
-
if (!Number.isFinite(part) || !Number.isFinite(total)) return null;
|
|
18694
|
-
if (part <= 0) return 0;
|
|
18695
|
-
return total > 0 ? part / total : null;
|
|
18696
|
-
}
|
|
18697
|
-
function breakdownShares(parts) {
|
|
18698
|
-
const total = parts.reduce((sum, part) => sum + Math.max(0, part), 0);
|
|
18699
|
-
return parts.map((part) => shareOf(part, total) ?? 0);
|
|
18700
|
-
}
|
|
18701
|
-
function median(values) {
|
|
18702
|
-
const sorted = values.filter((value) => Number.isFinite(value)).sort((left, right) => left - right);
|
|
18703
|
-
if (sorted.length === 0) return null;
|
|
18704
|
-
const middle = Math.floor(sorted.length / 2);
|
|
18705
|
-
return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
|
|
18706
|
-
}
|
|
18707
|
-
function wilsonInterval(successes, n, z97 = 1.96) {
|
|
18708
|
-
if (!Number.isFinite(n) || n <= 0) return null;
|
|
18709
|
-
const s = Math.max(0, Math.min(successes, n));
|
|
18710
|
-
const p = s / n;
|
|
18711
|
-
const z210 = z97 * z97;
|
|
18712
|
-
const denom = 1 + z210 / n;
|
|
18713
|
-
const center = (p + z210 / (2 * n)) / denom;
|
|
18714
|
-
const margin = z97 / denom * Math.sqrt(p * (1 - p) / n + z210 / (4 * n * n));
|
|
18715
|
-
return {
|
|
18716
|
-
low: round(Math.max(0, center - margin)),
|
|
18717
|
-
high: round(Math.min(1, center + margin))
|
|
18718
|
-
};
|
|
18719
|
-
}
|
|
18720
|
-
var linearTrendSchema = z56.object({
|
|
18721
|
-
/** Change in the fitted value per one-index step. */
|
|
18722
|
-
slope: z56.number(),
|
|
18723
|
-
/** Fitted value at index 0. */
|
|
18724
|
-
intercept: z56.number(),
|
|
18725
|
-
/** Coefficient of determination in [0, 1]. `1` for a series with no variance. */
|
|
18726
|
-
r2: z56.number(),
|
|
18727
|
-
/** Fitted value at the first index. */
|
|
18728
|
-
start: z56.number(),
|
|
18729
|
-
/** Fitted value at the last index. */
|
|
18730
|
-
end: z56.number(),
|
|
18731
|
-
/** Count of finite observations the fit used (not the series length). */
|
|
18732
|
-
n: z56.number(),
|
|
18733
|
-
/**
|
|
18734
|
-
* Index of the first observation the fit used, and of the last.
|
|
18735
|
-
*
|
|
18736
|
-
* `start` / `end` are evaluated AT these indices, not at the series' own ends.
|
|
18737
|
-
* A caller drawing the line must span exactly this range: extending it across
|
|
18738
|
-
* leading or trailing indices the metric has no data for draws a fitted claim
|
|
18739
|
-
* over dates that were never measured.
|
|
18740
|
-
*/
|
|
18741
|
-
startIndex: z56.number(),
|
|
18742
|
-
endIndex: z56.number()
|
|
18743
|
-
});
|
|
18744
|
-
function linearTrend(values) {
|
|
18745
|
-
const points = [];
|
|
18746
|
-
for (const [index, value] of values.entries()) {
|
|
18747
|
-
if (typeof value === "number" && Number.isFinite(value)) points.push({ x: index, y: value });
|
|
18748
|
-
}
|
|
18749
|
-
const n = points.length;
|
|
18750
|
-
if (n < 2) return null;
|
|
18751
|
-
const meanX = points.reduce((sum, p) => sum + p.x, 0) / n;
|
|
18752
|
-
const meanY = points.reduce((sum, p) => sum + p.y, 0) / n;
|
|
18753
|
-
let sxx = 0;
|
|
18754
|
-
let sxy = 0;
|
|
18755
|
-
for (const p of points) {
|
|
18756
|
-
sxx += (p.x - meanX) ** 2;
|
|
18757
|
-
sxy += (p.x - meanX) * (p.y - meanY);
|
|
18758
|
-
}
|
|
18759
|
-
const slope = sxy / sxx;
|
|
18760
|
-
const intercept = meanY - slope * meanX;
|
|
18761
|
-
let ssRes = 0;
|
|
18762
|
-
let ssTot = 0;
|
|
18763
|
-
for (const p of points) {
|
|
18764
|
-
ssRes += (p.y - (slope * p.x + intercept)) ** 2;
|
|
18765
|
-
ssTot += (p.y - meanY) ** 2;
|
|
18766
|
-
}
|
|
18767
|
-
const r2 = ssTot === 0 ? 1 : Math.min(1, Math.max(0, 1 - ssRes / ssTot));
|
|
18768
|
-
const firstX = points[0].x;
|
|
18769
|
-
const lastX = points[n - 1].x;
|
|
18770
|
-
return {
|
|
18771
|
-
slope: roundSignificant(slope),
|
|
18772
|
-
intercept: roundSignificant(intercept),
|
|
18773
|
-
r2: round(r2),
|
|
18774
|
-
start: roundSignificant(slope * firstX + intercept),
|
|
18775
|
-
end: roundSignificant(slope * lastX + intercept),
|
|
18776
|
-
n,
|
|
18777
|
-
startIndex: firstX,
|
|
18778
|
-
endIndex: lastX
|
|
18779
|
-
};
|
|
18780
|
-
}
|
|
18781
|
-
|
|
18782
18795
|
// ../contracts/src/traffic.ts
|
|
18783
18796
|
import { z as z57 } from "zod";
|
|
18784
18797
|
var trafficCrawlerSegmentsSchema = z57.object({
|
|
@@ -19214,6 +19227,17 @@ var trafficStatusResponseSchema = z57.object({
|
|
|
19214
19227
|
});
|
|
19215
19228
|
var trafficEventKindSchema = z57.enum(["crawler", "ai-user-fetch", "ai-referral"]);
|
|
19216
19229
|
var TrafficEventKinds = trafficEventKindSchema.enum;
|
|
19230
|
+
var TRAFFIC_EVENT_KIND_FILTER_HINT = `all, or one or more (comma-separated) of: ${trafficEventKindSchema.options.join(", ")}`;
|
|
19231
|
+
function parseTrafficEventKindFilter(value) {
|
|
19232
|
+
if (value === "all") return [...trafficEventKindSchema.options];
|
|
19233
|
+
const kinds = [];
|
|
19234
|
+
for (const member of value.split(",").map((part) => part.trim()).filter(Boolean)) {
|
|
19235
|
+
const parsed = trafficEventKindSchema.safeParse(member);
|
|
19236
|
+
if (!parsed.success) return null;
|
|
19237
|
+
if (!kinds.includes(parsed.data)) kinds.push(parsed.data);
|
|
19238
|
+
}
|
|
19239
|
+
return kinds.length > 0 ? kinds : null;
|
|
19240
|
+
}
|
|
19217
19241
|
var trafficSeriesGranularitySchema = z57.enum(["hour", "day"]);
|
|
19218
19242
|
var TrafficSeriesGranularities = trafficSeriesGranularitySchema.enum;
|
|
19219
19243
|
var trafficSeriesPointSchema = z57.object({
|
|
@@ -19321,6 +19345,16 @@ var trafficEventsResponseSchema = z57.object({
|
|
|
19321
19345
|
* early gap, which is the better error than marking real data unmeasured.
|
|
19322
19346
|
*/
|
|
19323
19347
|
coverageStart: z57.string().nullable(),
|
|
19348
|
+
/**
|
|
19349
|
+
* When the selected sources began counting AI-referral arrivals once per
|
|
19350
|
+
* visit, or null when none holds hours counted by the older rule. Hours
|
|
19351
|
+
* before it also counted a visitor's later pages, assets and API calls as
|
|
19352
|
+
* arrivals and read high; stored hourly rows keep no visitor, so they
|
|
19353
|
+
* cannot be recounted. Like `coverageStart`, not bound to the window.
|
|
19354
|
+
* `trends.aiReferralLandedHits` is fitted only over buckets that begin at
|
|
19355
|
+
* or after it. Optional so a newer client reads an older API.
|
|
19356
|
+
*/
|
|
19357
|
+
aiReferralCountingChangedAt: z57.string().nullable().optional(),
|
|
19324
19358
|
/**
|
|
19325
19359
|
* Least-squares fit per charted metric, over the densified points.
|
|
19326
19360
|
*
|
|
@@ -21435,6 +21469,14 @@ var trafficActivitySummarySchema = z66.object({
|
|
|
21435
21469
|
coverageStart: z66.string().nullable(),
|
|
21436
21470
|
/** Recording began on or before the prior window start. This does not establish uninterrupted ingestion. */
|
|
21437
21471
|
priorWindowComplete: z66.boolean(),
|
|
21472
|
+
/**
|
|
21473
|
+
* When the project's sources began counting AI-referral arrivals once per
|
|
21474
|
+
* visit, or null when none holds hours counted by the older rule. Earlier hours
|
|
21475
|
+
* also counted a visitor's later requests and read high, and cannot be
|
|
21476
|
+
* recounted, so referral deltas are null while the prior window starts
|
|
21477
|
+
* before it. Not window-bound. Optional so a newer client reads an older API.
|
|
21478
|
+
*/
|
|
21479
|
+
aiReferralCountingChangedAt: z66.string().nullable().optional(),
|
|
21438
21480
|
hasData: z66.boolean().describe("True when the selected or prior window has stored crawler, user-fetch, countable referral or operator evidence, or the selected window has referral redirects. False means no qualifying stored evidence; it can occur with no, paused, errored or never-synced ingestion and out-of-window observations. It does not establish measured zero traffic or source health."),
|
|
21439
21481
|
/** Verified crawler hits during the selected period and the equal preceding period. */
|
|
21440
21482
|
verifiedCrawlerHits: trafficActivityCountSchema,
|
|
@@ -28478,8 +28520,9 @@ export {
|
|
|
28478
28520
|
trafficSourceListResponseSchema,
|
|
28479
28521
|
trafficSourceDetailDtoSchema,
|
|
28480
28522
|
trafficStatusResponseSchema,
|
|
28481
|
-
trafficEventKindSchema,
|
|
28482
28523
|
TrafficEventKinds,
|
|
28524
|
+
TRAFFIC_EVENT_KIND_FILTER_HINT,
|
|
28525
|
+
parseTrafficEventKindFilter,
|
|
28483
28526
|
trafficSeriesGranularitySchema,
|
|
28484
28527
|
TrafficSeriesGranularities,
|
|
28485
28528
|
trafficEventsResponseSchema,
|