@canonry/canonry 4.134.0 → 4.135.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/canonry/references/aeo-analysis.md +3 -2
- package/assets/agent-workspace/skills/canonry/references/canonry-cli.md +34 -6
- package/assets/assets/{AuditHistoryPanel-DBUWbfNk.js → AuditHistoryPanel-BS0dmlrQ.js} +1 -1
- package/assets/assets/{BacklinksPage-BFm0VdUO.js → BacklinksPage-CPpWLVfa.js} +1 -1
- package/assets/assets/{ChartPrimitives-oV_nduTH.js → ChartPrimitives-Dv--2i87.js} +1 -1
- package/assets/assets/{HistoryPage-IF2FMem3.js → HistoryPage-BO4Fv-9q.js} +1 -1
- package/assets/assets/ProjectPage-Di_nDqtH.js +8 -0
- package/assets/assets/{RunRow-De5zdch5.js → RunRow-BE8zdGJ8.js} +1 -1
- package/assets/assets/{RunsPage-xtRF78r8.js → RunsPage-CbGanhaz.js} +1 -1
- package/assets/assets/{SettingsPage-B_GAxaWu.js → SettingsPage-odOpsOuf.js} +1 -1
- package/assets/assets/{TrafficPage-E8I5ineJ.js → TrafficPage-DK7oc0DK.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-DGk2MqSp.js → TrafficSourceDetailPage-CEFjQVuF.js} +1 -1
- package/assets/assets/{arrow-left-D-4QMxi9.js → arrow-left-DgzLEzZB.js} +1 -1
- package/assets/assets/{extract-error-message-DuqIFU8Z.js → extract-error-message-vlMjpZb2.js} +1 -1
- package/assets/assets/{index-De1MKbc7.js → index-BMlTgq7D.js} +72 -72
- package/assets/assets/{trash-2-BVh__r6G.js → trash-2-DX33Ys-K.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-TKXWTDV6.js → chunk-3PFRVEWP.js} +99 -31
- package/dist/{chunk-ZUQPHGEN.js → chunk-PAR6P5H6.js} +35 -3
- package/dist/{chunk-PC7AYXND.js → chunk-PXEEWJRV.js} +74 -20
- package/dist/{chunk-LIXWDIDR.js → chunk-TPVMHYHD.js} +188 -97
- package/dist/cli.js +63 -26
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-4XOFUN5E.js → intelligence-service-BMEJ5GFZ.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
- package/assets/assets/ProjectPage-ClwxX9Ga.js +0 -8
|
@@ -209,6 +209,7 @@ import {
|
|
|
209
209
|
formatNumber,
|
|
210
210
|
formatRatio,
|
|
211
211
|
formatWindowCountDelta,
|
|
212
|
+
ga4AiReferralDailyDtoSchema,
|
|
212
213
|
ga4AiReferralHistoryEntrySchema,
|
|
213
214
|
ga4SessionHistoryEntrySchema,
|
|
214
215
|
ga4SocialReferralHistoryEntrySchema,
|
|
@@ -364,7 +365,7 @@ import {
|
|
|
364
365
|
wordpressSchemaDeployResultDtoSchema,
|
|
365
366
|
wordpressSchemaStatusResultDtoSchema,
|
|
366
367
|
wordpressStatusDtoSchema
|
|
367
|
-
} from "./chunk-
|
|
368
|
+
} from "./chunk-PXEEWJRV.js";
|
|
368
369
|
|
|
369
370
|
// src/intelligence-service.ts
|
|
370
371
|
import { eq as eq44, desc as desc21, asc as asc9, and as and35, ne as ne6, or as or10, inArray as inArray15, gte as gte12, lte as lte8 } from "drizzle-orm";
|
|
@@ -17462,6 +17463,7 @@ var SCHEMA_TABLE = {
|
|
|
17462
17463
|
ResearchRunDetailDto: researchRunDetailSchema,
|
|
17463
17464
|
ResearchRunListDto: researchRunListSchema,
|
|
17464
17465
|
DoctorReportDto: doctorReportSchema,
|
|
17466
|
+
GA4AiReferralDailyDto: ga4AiReferralDailyDtoSchema,
|
|
17465
17467
|
GA4AiReferralHistoryEntry: ga4AiReferralHistoryEntrySchema,
|
|
17466
17468
|
GA4MeasurementAnalysisDto: gaMeasurementAnalysisDtoSchema,
|
|
17467
17469
|
GA4SessionHistoryEntry: ga4SessionHistoryEntrySchema,
|
|
@@ -21205,7 +21207,8 @@ var routeCatalog = [
|
|
|
21205
21207
|
{
|
|
21206
21208
|
method: "get",
|
|
21207
21209
|
path: "/api/v1/projects/{name}/ga/ai-referral-history",
|
|
21208
|
-
summary: "Get AI referral
|
|
21210
|
+
summary: "Get raw AI referral detail rows per day, landing page, and attribution dimension",
|
|
21211
|
+
description: "Detail rows, not totals. One row per landing page per attribution dimension, so a single day of one source is many rows and each is commonly worth one session. Use /ga/ai-referral-daily for per-date or per-source session counts.",
|
|
21209
21212
|
tags: ["ga4"],
|
|
21210
21213
|
parameters: [nameParameter, analyticsWindowParameter],
|
|
21211
21214
|
responses: {
|
|
@@ -21214,6 +21217,19 @@ var routeCatalog = [
|
|
|
21214
21217
|
404: errorResponse("Project not found.")
|
|
21215
21218
|
}
|
|
21216
21219
|
},
|
|
21220
|
+
{
|
|
21221
|
+
method: "get",
|
|
21222
|
+
path: "/api/v1/projects/{name}/ga/ai-referral-daily",
|
|
21223
|
+
summary: "Get AI referral sessions per day and per source",
|
|
21224
|
+
description: "Sums landing pages within one attribution dimension and never across dimensions, so totalSessions equals the aiSessionsDeduped reported by /ga/traffic for the same window. Sessions only: GA counts users as a distinct count at the grain requested, so an AI-referral user total cannot be summed from these rows and no un-dimensioned AI-referral fetch exists to supply one.",
|
|
21225
|
+
tags: ["ga4"],
|
|
21226
|
+
parameters: [nameParameter, analyticsWindowParameter],
|
|
21227
|
+
responses: {
|
|
21228
|
+
200: jsonResponse("AI referral daily series returned.", "GA4AiReferralDailyDto"),
|
|
21229
|
+
400: errorResponse("GA4 is not connected."),
|
|
21230
|
+
404: errorResponse("Project not found.")
|
|
21231
|
+
}
|
|
21232
|
+
},
|
|
21217
21233
|
{
|
|
21218
21234
|
method: "get",
|
|
21219
21235
|
path: "/api/v1/projects/{name}/ga/social-referral-history",
|
|
@@ -28709,11 +28725,17 @@ function storedSnapshotProvenance(input) {
|
|
|
28709
28725
|
sourceSync
|
|
28710
28726
|
};
|
|
28711
28727
|
}
|
|
28712
|
-
function
|
|
28728
|
+
function adsAccountToday(timezone, nowIso) {
|
|
28729
|
+
return formatIsoDateInTimeZone(nowIso, timezone ?? "UTC");
|
|
28730
|
+
}
|
|
28731
|
+
function inProgressWindowDate(newestDate, accountToday) {
|
|
28732
|
+
return newestDate !== null && newestDate === accountToday ? accountToday : null;
|
|
28733
|
+
}
|
|
28734
|
+
function historicalCampaignRollups(rows, accountToday) {
|
|
28713
28735
|
if (rows.length === 0) {
|
|
28714
28736
|
return {
|
|
28715
28737
|
status: AdsHistoricalCampaignRollupStatuses.unavailable,
|
|
28716
|
-
window: { from: null, to: null },
|
|
28738
|
+
window: { from: null, to: null, inProgressDate: null },
|
|
28717
28739
|
totals: null
|
|
28718
28740
|
};
|
|
28719
28741
|
}
|
|
@@ -28733,7 +28755,7 @@ function historicalCampaignRollups(rows) {
|
|
|
28733
28755
|
}
|
|
28734
28756
|
return {
|
|
28735
28757
|
status: AdsHistoricalCampaignRollupStatuses.reported,
|
|
28736
|
-
window: { from: fromDate, to: toDate },
|
|
28758
|
+
window: { from: fromDate, to: toDate, inProgressDate: inProgressWindowDate(toDate, accountToday) },
|
|
28737
28759
|
totals: {
|
|
28738
28760
|
impressions,
|
|
28739
28761
|
clicks,
|
|
@@ -30490,6 +30512,8 @@ async function adsRoutes(app, opts) {
|
|
|
30490
30512
|
if (from) conditions.push(gte8(adsInsightsDaily.date, from));
|
|
30491
30513
|
if (to) conditions.push(lte6(adsInsightsDaily.date, to));
|
|
30492
30514
|
const rows = app.db.select().from(adsInsightsDaily).where(and22(...conditions)).orderBy(asc6(adsInsightsDaily.date)).all();
|
|
30515
|
+
const conn = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
|
|
30516
|
+
const accountToday = adsAccountToday(conn?.timezone, (/* @__PURE__ */ new Date()).toISOString());
|
|
30493
30517
|
const dtoRows = rows.map((row) => ({
|
|
30494
30518
|
level: row.level,
|
|
30495
30519
|
entityId: row.entityId,
|
|
@@ -30499,9 +30523,9 @@ async function adsRoutes(app, opts) {
|
|
|
30499
30523
|
spendMicros: row.spendMicros,
|
|
30500
30524
|
conversions: row.conversions,
|
|
30501
30525
|
ctr: adsCtr(row.clicks, row.impressions),
|
|
30502
|
-
cpcMicros: adsCpcMicros(row.spendMicros, row.clicks)
|
|
30526
|
+
cpcMicros: adsCpcMicros(row.spendMicros, row.clicks),
|
|
30527
|
+
inProgress: row.date === accountToday
|
|
30503
30528
|
}));
|
|
30504
|
-
const conn = app.db.select().from(adsConnections).where(eq28(adsConnections.projectId, project.id)).get();
|
|
30505
30529
|
const response = { rows: dtoRows, currencyCode: conn?.currencyCode ?? null };
|
|
30506
30530
|
return response;
|
|
30507
30531
|
});
|
|
@@ -30531,7 +30555,7 @@ async function adsRoutes(app, opts) {
|
|
|
30531
30555
|
sourceSync,
|
|
30532
30556
|
latestAdsSync
|
|
30533
30557
|
});
|
|
30534
|
-
const
|
|
30558
|
+
const rollupRows = app.db.select({
|
|
30535
30559
|
date: adsInsightsDaily.date,
|
|
30536
30560
|
impressions: adsInsightsDaily.impressions,
|
|
30537
30561
|
clicks: adsInsightsDaily.clicks,
|
|
@@ -30540,7 +30564,11 @@ async function adsRoutes(app, opts) {
|
|
|
30540
30564
|
}).from(adsInsightsDaily).where(and22(
|
|
30541
30565
|
eq28(adsInsightsDaily.projectId, project.id),
|
|
30542
30566
|
eq28(adsInsightsDaily.level, AdsInsightLevels.campaign)
|
|
30543
|
-
)).all()
|
|
30567
|
+
)).all();
|
|
30568
|
+
const rollups = historicalCampaignRollups(
|
|
30569
|
+
rollupRows,
|
|
30570
|
+
adsAccountToday(connection?.timezone, (/* @__PURE__ */ new Date()).toISOString())
|
|
30571
|
+
);
|
|
30544
30572
|
const adsByGroup = /* @__PURE__ */ new Map();
|
|
30545
30573
|
for (const ad of adRows) {
|
|
30546
30574
|
const list = adsByGroup.get(ad.adGroupId) ?? [];
|
|
@@ -30846,7 +30874,9 @@ async function adsRoutes(app, opts) {
|
|
|
30846
30874
|
maxReaderCalls: ADS_LIVE_MAX_READER_CALLS,
|
|
30847
30875
|
readerCalls,
|
|
30848
30876
|
maxPagesPerReaderCall: liveDeliveryMaxPagesPerReaderCall,
|
|
30849
|
-
|
|
30877
|
+
// The +1 is the single-page in-progress-day request an insight
|
|
30878
|
+
// reader call makes alongside its paginating ranged walk.
|
|
30879
|
+
maxUpstreamHttpRequests: ADS_LIVE_MAX_READER_CALLS * (liveDeliveryMaxPagesPerReaderCall + 1),
|
|
30850
30880
|
truncated
|
|
30851
30881
|
},
|
|
30852
30882
|
entities,
|
|
@@ -30890,7 +30920,14 @@ async function adsRoutes(app, opts) {
|
|
|
30890
30920
|
campaignCount,
|
|
30891
30921
|
adGroupCount,
|
|
30892
30922
|
adCount,
|
|
30893
|
-
window: {
|
|
30923
|
+
window: {
|
|
30924
|
+
from: fromDate,
|
|
30925
|
+
to: toDate,
|
|
30926
|
+
inProgressDate: inProgressWindowDate(
|
|
30927
|
+
toDate,
|
|
30928
|
+
adsAccountToday(row?.timezone, (/* @__PURE__ */ new Date()).toISOString())
|
|
30929
|
+
)
|
|
30930
|
+
},
|
|
30894
30931
|
totals: {
|
|
30895
30932
|
impressions,
|
|
30896
30933
|
clicks,
|
|
@@ -31802,6 +31839,118 @@ function buildSessionHistory(landingPageDays, dailyTotals) {
|
|
|
31802
31839
|
});
|
|
31803
31840
|
}
|
|
31804
31841
|
|
|
31842
|
+
// ../api-routes/src/ga-ai-referral-aggregation.ts
|
|
31843
|
+
function normalizeAiTrafficClass(value) {
|
|
31844
|
+
return value === AiReferralTrafficClasses.paid ? AiReferralTrafficClasses.paid : AiReferralTrafficClasses.organic;
|
|
31845
|
+
}
|
|
31846
|
+
function emptyAiCounts() {
|
|
31847
|
+
return { sessions: 0 };
|
|
31848
|
+
}
|
|
31849
|
+
function resolveWinningDimensions(rows) {
|
|
31850
|
+
const groups = /* @__PURE__ */ new Map();
|
|
31851
|
+
for (const row of rows) {
|
|
31852
|
+
const key = `${row.date}\0${row.source}\0${row.medium}`;
|
|
31853
|
+
let group = groups.get(key);
|
|
31854
|
+
if (!group) {
|
|
31855
|
+
group = { date: row.date, source: row.source, medium: row.medium, byDimension: /* @__PURE__ */ new Map() };
|
|
31856
|
+
groups.set(key, group);
|
|
31857
|
+
}
|
|
31858
|
+
let dim = group.byDimension.get(row.sourceDimension);
|
|
31859
|
+
if (!dim) {
|
|
31860
|
+
dim = { paidSessions: 0, organicSessions: 0 };
|
|
31861
|
+
group.byDimension.set(row.sourceDimension, dim);
|
|
31862
|
+
}
|
|
31863
|
+
const sessions = row.sessions ?? 0;
|
|
31864
|
+
if (normalizeAiTrafficClass(row.trafficClass) === AiReferralTrafficClasses.paid) {
|
|
31865
|
+
dim.paidSessions += sessions;
|
|
31866
|
+
} else {
|
|
31867
|
+
dim.organicSessions += sessions;
|
|
31868
|
+
}
|
|
31869
|
+
}
|
|
31870
|
+
const winners = [];
|
|
31871
|
+
for (const group of groups.values()) {
|
|
31872
|
+
const dims = [...group.byDimension.values()];
|
|
31873
|
+
const bestSessions = dims.reduce((best, d) => d.paidSessions + d.organicSessions > best.paidSessions + best.organicSessions ? d : best);
|
|
31874
|
+
winners.push({
|
|
31875
|
+
date: group.date,
|
|
31876
|
+
source: group.source,
|
|
31877
|
+
medium: group.medium,
|
|
31878
|
+
paidSessions: bestSessions.paidSessions,
|
|
31879
|
+
organicSessions: bestSessions.organicSessions
|
|
31880
|
+
});
|
|
31881
|
+
}
|
|
31882
|
+
return winners;
|
|
31883
|
+
}
|
|
31884
|
+
function summarizeAiReferralCounts(rows) {
|
|
31885
|
+
const paidDeduped = emptyAiCounts();
|
|
31886
|
+
const organicDeduped = emptyAiCounts();
|
|
31887
|
+
const paidBySession = emptyAiCounts();
|
|
31888
|
+
const organicBySession = emptyAiCounts();
|
|
31889
|
+
const bySessionChannelGroup = /* @__PURE__ */ new Map();
|
|
31890
|
+
for (const winner of resolveWinningDimensions(rows)) {
|
|
31891
|
+
paidDeduped.sessions += winner.paidSessions;
|
|
31892
|
+
organicDeduped.sessions += winner.organicSessions;
|
|
31893
|
+
}
|
|
31894
|
+
for (const row of rows) {
|
|
31895
|
+
if (row.sourceDimension !== "session") continue;
|
|
31896
|
+
const sessions = row.sessions ?? 0;
|
|
31897
|
+
bySessionChannelGroup.set(
|
|
31898
|
+
row.channelGroup,
|
|
31899
|
+
(bySessionChannelGroup.get(row.channelGroup) ?? 0) + sessions
|
|
31900
|
+
);
|
|
31901
|
+
const bucket = normalizeAiTrafficClass(row.trafficClass) === AiReferralTrafficClasses.paid ? paidBySession : organicBySession;
|
|
31902
|
+
bucket.sessions += sessions;
|
|
31903
|
+
}
|
|
31904
|
+
return {
|
|
31905
|
+
paidDeduped,
|
|
31906
|
+
organicDeduped,
|
|
31907
|
+
paidBySession,
|
|
31908
|
+
organicBySession,
|
|
31909
|
+
bySessionChannelGroup,
|
|
31910
|
+
deduped: { sessions: paidDeduped.sessions + organicDeduped.sessions },
|
|
31911
|
+
bySession: { sessions: paidBySession.sessions + organicBySession.sessions }
|
|
31912
|
+
};
|
|
31913
|
+
}
|
|
31914
|
+
function buildAiReferralDailySeries(rows) {
|
|
31915
|
+
const byDate = /* @__PURE__ */ new Map();
|
|
31916
|
+
const sourceTotals = /* @__PURE__ */ new Map();
|
|
31917
|
+
let totalSessions = 0;
|
|
31918
|
+
let totalPaidSessions = 0;
|
|
31919
|
+
let totalOrganicSessions = 0;
|
|
31920
|
+
for (const winner of resolveWinningDimensions(rows)) {
|
|
31921
|
+
const sessions = winner.paidSessions + winner.organicSessions;
|
|
31922
|
+
let bySource = byDate.get(winner.date);
|
|
31923
|
+
if (!bySource) {
|
|
31924
|
+
bySource = /* @__PURE__ */ new Map();
|
|
31925
|
+
byDate.set(winner.date, bySource);
|
|
31926
|
+
}
|
|
31927
|
+
let bucket = bySource.get(winner.source);
|
|
31928
|
+
if (!bucket) {
|
|
31929
|
+
bucket = { source: winner.source, sessions: 0, paidSessions: 0, organicSessions: 0 };
|
|
31930
|
+
bySource.set(winner.source, bucket);
|
|
31931
|
+
}
|
|
31932
|
+
bucket.sessions += sessions;
|
|
31933
|
+
bucket.paidSessions += winner.paidSessions;
|
|
31934
|
+
bucket.organicSessions += winner.organicSessions;
|
|
31935
|
+
sourceTotals.set(winner.source, (sourceTotals.get(winner.source) ?? 0) + sessions);
|
|
31936
|
+
totalSessions += sessions;
|
|
31937
|
+
totalPaidSessions += winner.paidSessions;
|
|
31938
|
+
totalOrganicSessions += winner.organicSessions;
|
|
31939
|
+
}
|
|
31940
|
+
const days = [...byDate.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([date, bySource]) => {
|
|
31941
|
+
const sources2 = [...bySource.values()].sort((a, b) => b.sessions - a.sessions || a.source.localeCompare(b.source));
|
|
31942
|
+
return {
|
|
31943
|
+
date,
|
|
31944
|
+
sessions: sources2.reduce((sum, s) => sum + s.sessions, 0),
|
|
31945
|
+
paidSessions: sources2.reduce((sum, s) => sum + s.paidSessions, 0),
|
|
31946
|
+
organicSessions: sources2.reduce((sum, s) => sum + s.organicSessions, 0),
|
|
31947
|
+
bySource: sources2
|
|
31948
|
+
};
|
|
31949
|
+
});
|
|
31950
|
+
const sources = [...sourceTotals.entries()].sort(([aSource, aSessions], [bSource, bSessions]) => bSessions - aSessions || aSource.localeCompare(bSource)).map(([source]) => source);
|
|
31951
|
+
return { days, sources, totalSessions, totalPaidSessions, totalOrganicSessions };
|
|
31952
|
+
}
|
|
31953
|
+
|
|
31805
31954
|
// ../api-routes/src/ga.ts
|
|
31806
31955
|
function gaLog(level, action, ctx) {
|
|
31807
31956
|
const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), level, module: "GA4Routes", action, ...ctx };
|
|
@@ -31858,12 +32007,6 @@ function pickWinningDimension(rows, tupleKey) {
|
|
|
31858
32007
|
}
|
|
31859
32008
|
return [...winners.values()].sort((a, b) => (b.sessions ?? 0) - (a.sessions ?? 0));
|
|
31860
32009
|
}
|
|
31861
|
-
function normalizeAiTrafficClass(value) {
|
|
31862
|
-
return value === AiReferralTrafficClasses.paid ? AiReferralTrafficClasses.paid : AiReferralTrafficClasses.organic;
|
|
31863
|
-
}
|
|
31864
|
-
function emptyAiCounts() {
|
|
31865
|
-
return { sessions: 0, users: 0 };
|
|
31866
|
-
}
|
|
31867
32010
|
function persistAcquisitionMeasurement(db, input) {
|
|
31868
32011
|
const { startDate, endDate } = input.report;
|
|
31869
32012
|
db.transaction((tx) => {
|
|
@@ -31992,70 +32135,6 @@ function persistMeasurementError(db, projectId, component, message, updatedAt) {
|
|
|
31992
32135
|
}
|
|
31993
32136
|
}).run();
|
|
31994
32137
|
}
|
|
31995
|
-
function summarizeAiReferralCounts(rows) {
|
|
31996
|
-
const dedupeGroups = /* @__PURE__ */ new Map();
|
|
31997
|
-
const bySessionChannelGroup = /* @__PURE__ */ new Map();
|
|
31998
|
-
const paidDeduped = emptyAiCounts();
|
|
31999
|
-
const organicDeduped = emptyAiCounts();
|
|
32000
|
-
const paidBySession = emptyAiCounts();
|
|
32001
|
-
const organicBySession = emptyAiCounts();
|
|
32002
|
-
for (const row of rows) {
|
|
32003
|
-
const isPaid = normalizeAiTrafficClass(row.trafficClass) === AiReferralTrafficClasses.paid;
|
|
32004
|
-
const sessions = row.sessions ?? 0;
|
|
32005
|
-
const users = row.users ?? 0;
|
|
32006
|
-
const key = `${row.date}\0${row.source}\0${row.medium}`;
|
|
32007
|
-
let byDimension = dedupeGroups.get(key);
|
|
32008
|
-
if (!byDimension) {
|
|
32009
|
-
byDimension = /* @__PURE__ */ new Map();
|
|
32010
|
-
dedupeGroups.set(key, byDimension);
|
|
32011
|
-
}
|
|
32012
|
-
let dim = byDimension.get(row.sourceDimension);
|
|
32013
|
-
if (!dim) {
|
|
32014
|
-
dim = { paidSessions: 0, organicSessions: 0, paidUsers: 0, organicUsers: 0 };
|
|
32015
|
-
byDimension.set(row.sourceDimension, dim);
|
|
32016
|
-
}
|
|
32017
|
-
if (isPaid) {
|
|
32018
|
-
dim.paidSessions += sessions;
|
|
32019
|
-
dim.paidUsers += users;
|
|
32020
|
-
} else {
|
|
32021
|
-
dim.organicSessions += sessions;
|
|
32022
|
-
dim.organicUsers += users;
|
|
32023
|
-
}
|
|
32024
|
-
if (row.sourceDimension === "session") {
|
|
32025
|
-
bySessionChannelGroup.set(
|
|
32026
|
-
row.channelGroup,
|
|
32027
|
-
(bySessionChannelGroup.get(row.channelGroup) ?? 0) + sessions
|
|
32028
|
-
);
|
|
32029
|
-
const sessionBucket = isPaid ? paidBySession : organicBySession;
|
|
32030
|
-
sessionBucket.sessions += sessions;
|
|
32031
|
-
sessionBucket.users += users;
|
|
32032
|
-
}
|
|
32033
|
-
}
|
|
32034
|
-
for (const byDimension of dedupeGroups.values()) {
|
|
32035
|
-
const dims = [...byDimension.values()];
|
|
32036
|
-
const bestSessions = dims.reduce((best, d) => d.paidSessions + d.organicSessions > best.paidSessions + best.organicSessions ? d : best);
|
|
32037
|
-
const bestUsers = dims.reduce((best, d) => d.paidUsers + d.organicUsers > best.paidUsers + best.organicUsers ? d : best);
|
|
32038
|
-
paidDeduped.sessions += bestSessions.paidSessions;
|
|
32039
|
-
organicDeduped.sessions += bestSessions.organicSessions;
|
|
32040
|
-
paidDeduped.users += bestUsers.paidUsers;
|
|
32041
|
-
organicDeduped.users += bestUsers.organicUsers;
|
|
32042
|
-
}
|
|
32043
|
-
return {
|
|
32044
|
-
paidDeduped,
|
|
32045
|
-
organicDeduped,
|
|
32046
|
-
paidBySession,
|
|
32047
|
-
organicBySession,
|
|
32048
|
-
bySessionChannelGroup,
|
|
32049
|
-
deduped: {
|
|
32050
|
-
sessions: paidDeduped.sessions + organicDeduped.sessions,
|
|
32051
|
-
users: paidDeduped.users + organicDeduped.users
|
|
32052
|
-
},
|
|
32053
|
-
bySession: {
|
|
32054
|
-
sessions: paidBySession.sessions + organicBySession.sessions,
|
|
32055
|
-
users: paidBySession.users + organicBySession.users
|
|
32056
|
-
}
|
|
32057
|
-
};
|
|
32058
|
-
}
|
|
32059
32138
|
async function refreshOAuthTokenIfNeeded(googleStore, authConfig, canonicalDomain, oauthConn) {
|
|
32060
32139
|
const expiresAt = oauthConn.tokenExpiresAt ? new Date(oauthConn.tokenExpiresAt).getTime() : 0;
|
|
32061
32140
|
const fiveMinutes = 5 * 60 * 1e3;
|
|
@@ -32590,8 +32669,7 @@ async function ga4Routes(app, opts) {
|
|
|
32590
32669
|
medium: gaAiReferrals.medium,
|
|
32591
32670
|
trafficClass: gaAiReferrals.trafficClass,
|
|
32592
32671
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
32593
|
-
sessions: sql15`SUM(${gaAiReferrals.sessions})
|
|
32594
|
-
users: sql15`SUM(${gaAiReferrals.users})`
|
|
32672
|
+
sessions: sql15`SUM(${gaAiReferrals.sessions})`
|
|
32595
32673
|
}).from(gaAiReferrals).where(and25(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.trafficClass, gaAiReferrals.sourceDimension).all();
|
|
32596
32674
|
const aiReferralLandingPageRows = app.db.select({
|
|
32597
32675
|
source: gaAiReferrals.source,
|
|
@@ -32599,8 +32677,7 @@ async function ga4Routes(app, opts) {
|
|
|
32599
32677
|
trafficClass: gaAiReferrals.trafficClass,
|
|
32600
32678
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
32601
32679
|
landingPage: sql15`COALESCE(${gaAiReferrals.landingPageNormalized}, ${gaAiReferrals.landingPage})`,
|
|
32602
|
-
sessions: sql15`SUM(${gaAiReferrals.sessions})
|
|
32603
|
-
users: sql15`SUM(${gaAiReferrals.users})`
|
|
32680
|
+
sessions: sql15`SUM(${gaAiReferrals.sessions})`
|
|
32604
32681
|
}).from(gaAiReferrals).where(and25(...aiConditions)).groupBy(
|
|
32605
32682
|
gaAiReferrals.source,
|
|
32606
32683
|
gaAiReferrals.medium,
|
|
@@ -32615,8 +32692,7 @@ async function ga4Routes(app, opts) {
|
|
|
32615
32692
|
trafficClass: gaAiReferrals.trafficClass,
|
|
32616
32693
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
32617
32694
|
channelGroup: gaAiReferrals.channelGroup,
|
|
32618
|
-
sessions: gaAiReferrals.sessions
|
|
32619
|
-
users: gaAiReferrals.users
|
|
32695
|
+
sessions: gaAiReferrals.sessions
|
|
32620
32696
|
}).from(gaAiReferrals).where(and25(...aiConditions)).all();
|
|
32621
32697
|
const aiReferrals = pickWinningDimension(
|
|
32622
32698
|
aiReferralRows,
|
|
@@ -32662,13 +32738,18 @@ async function ga4Routes(app, opts) {
|
|
|
32662
32738
|
directSessions: r.directSessions ?? 0,
|
|
32663
32739
|
users: r.users ?? 0
|
|
32664
32740
|
})),
|
|
32741
|
+
// No `users` on either referral row type, and no `ai*Users*` totals: GA
|
|
32742
|
+
// reports users as a COUNT DISTINCT at the grain requested, so summing
|
|
32743
|
+
// the stored column across landing pages (and, for these rows, across
|
|
32744
|
+
// every date in the window) counted one visitor once per row. Withdrawn
|
|
32745
|
+
// in 4.135.0; see `ga-ai-referral-aggregation.ts` for why no correct
|
|
32746
|
+
// figure can be computed or fetched.
|
|
32665
32747
|
aiReferrals: aiReferrals.map((r) => ({
|
|
32666
32748
|
source: r.source,
|
|
32667
32749
|
medium: r.medium,
|
|
32668
32750
|
trafficClass: normalizeAiTrafficClass(r.trafficClass),
|
|
32669
32751
|
sourceDimension: r.sourceDimension,
|
|
32670
|
-
sessions: r.sessions ?? 0
|
|
32671
|
-
users: r.users ?? 0
|
|
32752
|
+
sessions: r.sessions ?? 0
|
|
32672
32753
|
})),
|
|
32673
32754
|
aiReferralLandingPages: aiReferralLandingPages.map((r) => ({
|
|
32674
32755
|
source: r.source,
|
|
@@ -32676,21 +32757,14 @@ async function ga4Routes(app, opts) {
|
|
|
32676
32757
|
trafficClass: normalizeAiTrafficClass(r.trafficClass),
|
|
32677
32758
|
sourceDimension: r.sourceDimension,
|
|
32678
32759
|
landingPage: r.landingPage,
|
|
32679
|
-
sessions: r.sessions ?? 0
|
|
32680
|
-
users: r.users ?? 0
|
|
32760
|
+
sessions: r.sessions ?? 0
|
|
32681
32761
|
})),
|
|
32682
32762
|
aiSessionsDeduped: aiSummary.deduped.sessions,
|
|
32683
|
-
aiUsersDeduped: aiSummary.deduped.users,
|
|
32684
32763
|
paidAiSessionsDeduped: aiSummary.paidDeduped.sessions,
|
|
32685
|
-
paidAiUsersDeduped: aiSummary.paidDeduped.users,
|
|
32686
32764
|
organicAiSessionsDeduped: aiSummary.organicDeduped.sessions,
|
|
32687
|
-
organicAiUsersDeduped: aiSummary.organicDeduped.users,
|
|
32688
32765
|
aiSessionsBySession: aiSummary.bySession.sessions,
|
|
32689
|
-
aiUsersBySession: aiSummary.bySession.users,
|
|
32690
32766
|
paidAiSessionsBySession: aiSummary.paidBySession.sessions,
|
|
32691
|
-
paidAiUsersBySession: aiSummary.paidBySession.users,
|
|
32692
32767
|
organicAiSessionsBySession: aiSummary.organicBySession.sessions,
|
|
32693
|
-
organicAiUsersBySession: aiSummary.organicBySession.users,
|
|
32694
32768
|
socialReferrals: socialReferrals.map((r) => ({
|
|
32695
32769
|
source: r.source,
|
|
32696
32770
|
medium: r.medium,
|
|
@@ -32757,6 +32831,23 @@ async function ga4Routes(app, opts) {
|
|
|
32757
32831
|
).orderBy(gaAiReferrals.date).all();
|
|
32758
32832
|
return rows;
|
|
32759
32833
|
});
|
|
32834
|
+
app.get("/projects/:name/ga/ai-referral-daily", async (request, _reply) => {
|
|
32835
|
+
const project = resolveProject(app.db, request.params.name);
|
|
32836
|
+
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
32837
|
+
const cutoffDate = windowCutoff(parseWindow(request.query.window))?.slice(0, 10) ?? null;
|
|
32838
|
+
const conditions = [eq31(gaAiReferrals.projectId, project.id)];
|
|
32839
|
+
if (cutoffDate) conditions.push(sql15`${gaAiReferrals.date} >= ${cutoffDate}`);
|
|
32840
|
+
const rows = app.db.select({
|
|
32841
|
+
date: gaAiReferrals.date,
|
|
32842
|
+
source: gaAiReferrals.source,
|
|
32843
|
+
medium: gaAiReferrals.medium,
|
|
32844
|
+
trafficClass: gaAiReferrals.trafficClass,
|
|
32845
|
+
sourceDimension: gaAiReferrals.sourceDimension,
|
|
32846
|
+
channelGroup: gaAiReferrals.channelGroup,
|
|
32847
|
+
sessions: gaAiReferrals.sessions
|
|
32848
|
+
}).from(gaAiReferrals).where(and25(...conditions)).all();
|
|
32849
|
+
return buildAiReferralDailySeries(rows);
|
|
32850
|
+
});
|
|
32760
32851
|
app.get("/projects/:name/ga/social-referral-history", async (request, _reply) => {
|
|
32761
32852
|
const project = resolveProject(app.db, request.params.name);
|
|
32762
32853
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
package/dist/cli.js
CHANGED
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
setTelemetrySource,
|
|
30
30
|
showFirstRunNotice,
|
|
31
31
|
trackEvent
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-3PFRVEWP.js";
|
|
33
33
|
import {
|
|
34
34
|
CliError,
|
|
35
35
|
EXIT_SYSTEM_ERROR,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
saveConfig,
|
|
47
47
|
saveConfigPatch,
|
|
48
48
|
usageError
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-PAR6P5H6.js";
|
|
50
50
|
import {
|
|
51
51
|
apiKeys,
|
|
52
52
|
createClient,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
projects,
|
|
55
55
|
queries,
|
|
56
56
|
renderReportHtml
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-TPVMHYHD.js";
|
|
58
58
|
import {
|
|
59
59
|
AdsDeliverySnapshotStatuses,
|
|
60
60
|
AdsHistoricalCampaignRollupStatuses,
|
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
providerQuotaPolicySchema,
|
|
101
101
|
resolveProviderInput,
|
|
102
102
|
winnabilityClassSchema
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-PXEEWJRV.js";
|
|
104
104
|
|
|
105
105
|
// src/cli.ts
|
|
106
106
|
import { pathToFileURL } from "url";
|
|
@@ -3012,6 +3012,9 @@ function readRequest(inputPath, schema) {
|
|
|
3012
3012
|
});
|
|
3013
3013
|
}
|
|
3014
3014
|
}
|
|
3015
|
+
function partialDayNote(inProgressDate) {
|
|
3016
|
+
return inProgressDate === null ? "" : ` (${inProgressDate} still filling)`;
|
|
3017
|
+
}
|
|
3015
3018
|
function printOperationDetails(operation) {
|
|
3016
3019
|
console.log(`Operation: ${operation.operationKey}`);
|
|
3017
3020
|
if (operation.entityId) console.log(`Entity: ${operation.entityType ?? "unknown"} ${operation.entityId}`);
|
|
@@ -3366,8 +3369,9 @@ async function adsInsights(project, opts) {
|
|
|
3366
3369
|
console.log("DATE LEVEL ENTITY IMPR CLICKS SPEND CPC");
|
|
3367
3370
|
for (const row of result.rows) {
|
|
3368
3371
|
const cpc = row.cpcMicros != null ? formatMicros(row.cpcMicros, currency) : "\u2014";
|
|
3372
|
+
const partial = row.inProgress ? " (still filling)" : "";
|
|
3369
3373
|
console.log(
|
|
3370
|
-
`${row.date} ${row.level.padEnd(9)} ${row.entityId.padEnd(36).slice(0, 36)} ${String(row.impressions).padStart(6)} ${String(row.clicks).padStart(6)} ${formatMicros(row.spendMicros, currency).padStart(9)} ${cpc}`
|
|
3374
|
+
`${row.date} ${row.level.padEnd(9)} ${row.entityId.padEnd(36).slice(0, 36)} ${String(row.impressions).padStart(6)} ${String(row.clicks).padStart(6)} ${formatMicros(row.spendMicros, currency).padStart(9)} ${cpc}${partial}`
|
|
3371
3375
|
);
|
|
3372
3376
|
}
|
|
3373
3377
|
}
|
|
@@ -3384,7 +3388,7 @@ async function adsSummary(project, opts) {
|
|
|
3384
3388
|
}
|
|
3385
3389
|
console.log(`Account: ${result.displayName ?? "unknown"} (${result.currencyCode ?? "?"})`);
|
|
3386
3390
|
console.log(`Structure: ${result.campaignCount} campaigns / ${result.adGroupCount} ad groups / ${result.adCount} ads`);
|
|
3387
|
-
console.log(`Window: ${result.window.from ?? "\u2014"} \u2192 ${result.window.to ?? "\u2014"}`);
|
|
3391
|
+
console.log(`Window: ${result.window.from ?? "\u2014"} \u2192 ${result.window.to ?? "\u2014"}${partialDayNote(result.window.inProgressDate)}`);
|
|
3388
3392
|
console.log(`Impressions: ${result.totals.impressions}`);
|
|
3389
3393
|
console.log(`Clicks: ${result.totals.clicks}${result.totals.ctr != null ? ` (CTR ${(result.totals.ctr * 100).toFixed(2)}%)` : ""}`);
|
|
3390
3394
|
console.log(`Spend: ${formatMicros(result.totals.spendMicros, result.currencyCode ?? "USD")}${result.totals.cpcMicros != null ? ` (CPC ${formatMicros(result.totals.cpcMicros, result.currencyCode ?? "USD")})` : ""}`);
|
|
@@ -3402,7 +3406,8 @@ async function adsDeliveryDiagnostics(project, opts) {
|
|
|
3402
3406
|
console.log(`Last synced: ${result.snapshot.lastSyncedAt ?? "never"}`);
|
|
3403
3407
|
console.log(`Activity: ${result.assessment.state}`);
|
|
3404
3408
|
if (result.historicalCampaignRollups.status === AdsHistoricalCampaignRollupStatuses.reported && result.historicalCampaignRollups.totals !== null) {
|
|
3405
|
-
|
|
3409
|
+
const rollupWindow = result.historicalCampaignRollups.window;
|
|
3410
|
+
console.log(`Historical: ${result.historicalCampaignRollups.totals.impressions} impressions / ${result.historicalCampaignRollups.totals.clicks} clicks (${rollupWindow.from} \u2192 ${rollupWindow.to})${partialDayNote(rollupWindow.inProgressDate)}`);
|
|
3406
3411
|
} else {
|
|
3407
3412
|
console.log("Historical: no stored campaign rollups");
|
|
3408
3413
|
}
|
|
@@ -3982,13 +3987,13 @@ async function gaTraffic(project, opts) {
|
|
|
3982
3987
|
const attrWidth = 12;
|
|
3983
3988
|
const classWidth = 8;
|
|
3984
3989
|
console.log(" AI REFERRAL SOURCES");
|
|
3985
|
-
console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CLASS".padEnd(classWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}
|
|
3986
|
-
console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(classWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}
|
|
3990
|
+
console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CLASS".padEnd(classWidth)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}`);
|
|
3991
|
+
console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(classWidth)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}`);
|
|
3987
3992
|
for (const ref of result.aiReferrals) {
|
|
3988
3993
|
const dimLabel = ref.sourceDimension === "first_user" ? "first-visit" : ref.sourceDimension === "manual_utm" ? "utm" : "session";
|
|
3989
3994
|
const classLabel = ref.trafficClass === "paid" ? "paid" : "organic";
|
|
3990
3995
|
console.log(
|
|
3991
|
-
` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${classLabel.padEnd(classWidth)} ${dimLabel.padEnd(attrWidth)} ${String(ref.sessions).padEnd(10)}
|
|
3996
|
+
` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${classLabel.padEnd(classWidth)} ${dimLabel.padEnd(attrWidth)} ${String(ref.sessions).padEnd(10)}`
|
|
3992
3997
|
);
|
|
3993
3998
|
}
|
|
3994
3999
|
console.log();
|
|
@@ -3996,14 +4001,14 @@ async function gaTraffic(project, opts) {
|
|
|
3996
4001
|
if (result.aiReferralLandingPages.length > 0) {
|
|
3997
4002
|
const attrWidth = 12;
|
|
3998
4003
|
console.log(" AI REFERRAL LANDING PAGES");
|
|
3999
|
-
console.log(` ${"LANDING PAGE".padEnd(30)} ${"SOURCE".padEnd(25)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}
|
|
4000
|
-
console.log(` ${"\u2500".repeat(30)} ${"\u2500".repeat(25)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}
|
|
4004
|
+
console.log(` ${"LANDING PAGE".padEnd(30)} ${"SOURCE".padEnd(25)} ${"ATTRIBUTION".padEnd(attrWidth)} ${"SESSIONS".padEnd(10)}`);
|
|
4005
|
+
console.log(` ${"\u2500".repeat(30)} ${"\u2500".repeat(25)} ${"\u2500".repeat(attrWidth)} ${"\u2500".repeat(10)}`);
|
|
4001
4006
|
for (const row of result.aiReferralLandingPages) {
|
|
4002
4007
|
const dimLabel = row.sourceDimension === "first_user" ? "first-visit" : row.sourceDimension === "manual_utm" ? "utm" : "session";
|
|
4003
4008
|
const page = row.landingPage.length > 30 ? row.landingPage.slice(0, 27) + "..." : row.landingPage;
|
|
4004
4009
|
const source = row.source.length > 25 ? row.source.slice(0, 22) + "..." : row.source;
|
|
4005
4010
|
console.log(
|
|
4006
|
-
` ${page.padEnd(30)} ${source.padEnd(25)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}
|
|
4011
|
+
` ${page.padEnd(30)} ${source.padEnd(25)} ${dimLabel.padEnd(attrWidth)} ${String(row.sessions).padEnd(10)}`
|
|
4007
4012
|
);
|
|
4008
4013
|
}
|
|
4009
4014
|
console.log();
|
|
@@ -4111,6 +4116,36 @@ async function gaAiReferralHistory(project, opts) {
|
|
|
4111
4116
|
);
|
|
4112
4117
|
}
|
|
4113
4118
|
}
|
|
4119
|
+
async function gaAiReferralDaily(project, opts) {
|
|
4120
|
+
const client = getClient7();
|
|
4121
|
+
const result = await client.gaAiReferralDaily(project, opts?.window ? { window: opts.window } : void 0);
|
|
4122
|
+
if (opts?.format === "json") {
|
|
4123
|
+
console.log(JSON.stringify(result, null, 2));
|
|
4124
|
+
return;
|
|
4125
|
+
} else if (opts?.format === "jsonl") {
|
|
4126
|
+
emitJsonl(result.days.map((day) => ({ project, window: opts?.window, ...day })));
|
|
4127
|
+
return;
|
|
4128
|
+
}
|
|
4129
|
+
if (result.days.length === 0) {
|
|
4130
|
+
console.log(`No AI referral sessions.${opts?.window ? " Try a wider window or omit --window." : ' Run "canonry ga sync <project>" first.'}`);
|
|
4131
|
+
return;
|
|
4132
|
+
}
|
|
4133
|
+
const dateWidth = 12;
|
|
4134
|
+
const sourceWidth = Math.min(30, Math.max(10, ...result.sources.map((s) => s.length)));
|
|
4135
|
+
console.log(`GA4 AI Referral Sessions per Day for "${project}":
|
|
4136
|
+
`);
|
|
4137
|
+
console.log(` ${"DATE".padEnd(dateWidth)} ${"SOURCE".padEnd(sourceWidth)} ${"SESSIONS".padEnd(10)}${"PAID".padEnd(8)}${"ORGANIC".padEnd(9)}`);
|
|
4138
|
+
console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(sourceWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}${"\u2500".repeat(9)}`);
|
|
4139
|
+
for (const day of result.days) {
|
|
4140
|
+
for (const entry of day.bySource) {
|
|
4141
|
+
console.log(
|
|
4142
|
+
` ${day.date.padEnd(dateWidth)} ${entry.source.padEnd(sourceWidth)} ${String(entry.sessions).padEnd(10)}${String(entry.paidSessions).padEnd(8)}${String(entry.organicSessions).padEnd(9)}`
|
|
4143
|
+
);
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
4146
|
+
console.log(`
|
|
4147
|
+
Total: ${result.totalSessions} sessions (${result.totalPaidSessions} paid, ${result.totalOrganicSessions} organic)`);
|
|
4148
|
+
}
|
|
4114
4149
|
async function gaSocialReferralHistory(project, opts) {
|
|
4115
4150
|
const client = getClient7();
|
|
4116
4151
|
const result = await client.gaSocialReferralHistory(project, opts?.window ? { window: opts.window } : void 0);
|
|
@@ -4269,17 +4304,11 @@ async function gaAttribution(project, opts) {
|
|
|
4269
4304
|
totalUsers: traffic.totalUsers,
|
|
4270
4305
|
organicSessions: traffic.totalOrganicSessions,
|
|
4271
4306
|
aiSessions: traffic.aiSessionsDeduped,
|
|
4272
|
-
aiUsers: traffic.aiUsersDeduped,
|
|
4273
4307
|
paidAiSessions: traffic.paidAiSessionsDeduped,
|
|
4274
|
-
paidAiUsers: traffic.paidAiUsersDeduped,
|
|
4275
4308
|
organicAiSessions: traffic.organicAiSessionsDeduped,
|
|
4276
|
-
organicAiUsers: traffic.organicAiUsersDeduped,
|
|
4277
4309
|
aiSessionsBySession: traffic.aiSessionsBySession,
|
|
4278
|
-
aiUsersBySession: traffic.aiUsersBySession,
|
|
4279
4310
|
paidAiSessionsBySession: traffic.paidAiSessionsBySession,
|
|
4280
|
-
paidAiUsersBySession: traffic.paidAiUsersBySession,
|
|
4281
4311
|
organicAiSessionsBySession: traffic.organicAiSessionsBySession,
|
|
4282
|
-
organicAiUsersBySession: traffic.organicAiUsersBySession,
|
|
4283
4312
|
socialSessions: traffic.socialSessions,
|
|
4284
4313
|
socialUsers: traffic.socialUsers,
|
|
4285
4314
|
directSessions: traffic.totalDirectSessions,
|
|
@@ -4356,17 +4385,11 @@ async function gaAttribution(project, opts) {
|
|
|
4356
4385
|
totalUsers: traffic.totalUsers,
|
|
4357
4386
|
organicSessions: traffic.totalOrganicSessions,
|
|
4358
4387
|
aiSessions: traffic.aiSessionsDeduped,
|
|
4359
|
-
aiUsers: traffic.aiUsersDeduped,
|
|
4360
4388
|
paidAiSessions: traffic.paidAiSessionsDeduped,
|
|
4361
|
-
paidAiUsers: traffic.paidAiUsersDeduped,
|
|
4362
4389
|
organicAiSessions: traffic.organicAiSessionsDeduped,
|
|
4363
|
-
organicAiUsers: traffic.organicAiUsersDeduped,
|
|
4364
4390
|
aiSessionsBySession: traffic.aiSessionsBySession,
|
|
4365
|
-
aiUsersBySession: traffic.aiUsersBySession,
|
|
4366
4391
|
paidAiSessionsBySession: traffic.paidAiSessionsBySession,
|
|
4367
|
-
paidAiUsersBySession: traffic.paidAiUsersBySession,
|
|
4368
4392
|
organicAiSessionsBySession: traffic.organicAiSessionsBySession,
|
|
4369
|
-
organicAiUsersBySession: traffic.organicAiUsersBySession,
|
|
4370
4393
|
socialSessions: traffic.socialSessions,
|
|
4371
4394
|
socialUsers: traffic.socialUsers,
|
|
4372
4395
|
directSessions: traffic.totalDirectSessions,
|
|
@@ -4575,6 +4598,20 @@ var GA_CLI_COMMANDS = [
|
|
|
4575
4598
|
});
|
|
4576
4599
|
}
|
|
4577
4600
|
},
|
|
4601
|
+
{
|
|
4602
|
+
path: ["ga", "ai-referral-daily"],
|
|
4603
|
+
usage: "canonry ga ai-referral-daily <project> [--window 30d] [--format json]",
|
|
4604
|
+
options: {
|
|
4605
|
+
window: stringOption()
|
|
4606
|
+
},
|
|
4607
|
+
run: async (input) => {
|
|
4608
|
+
const project = requireProject(input, "ga.ai-referral-daily", "canonry ga ai-referral-daily <project> [--window 30d] [--format json]");
|
|
4609
|
+
await gaAiReferralDaily(project, {
|
|
4610
|
+
window: getString(input.values, "window"),
|
|
4611
|
+
format: input.format
|
|
4612
|
+
});
|
|
4613
|
+
}
|
|
4614
|
+
},
|
|
4578
4615
|
{
|
|
4579
4616
|
path: ["ga", "social-referral-history"],
|
|
4580
4617
|
usage: "canonry ga social-referral-history <project> [--window 30d] [--format json]",
|
|
@@ -4638,7 +4675,7 @@ var GA_CLI_COMMANDS = [
|
|
|
4638
4675
|
unknownSubcommand(input.positionals[0], {
|
|
4639
4676
|
command: "ga",
|
|
4640
4677
|
usage: "canonry ga <subcommand> <project> [args]",
|
|
4641
|
-
available: ["connect", "disconnect", "status", "sync", "measurement-analysis", "traffic", "coverage", "ai-referral-history", "social-referral-history", "session-history", "social-referral-summary", "attribution"]
|
|
4678
|
+
available: ["connect", "disconnect", "status", "sync", "measurement-analysis", "traffic", "coverage", "ai-referral-history", "ai-referral-daily", "social-referral-history", "session-history", "social-referral-summary", "attribution"]
|
|
4642
4679
|
});
|
|
4643
4680
|
}
|
|
4644
4681
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createServer
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3PFRVEWP.js";
|
|
4
4
|
import {
|
|
5
5
|
loadConfig
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-PAR6P5H6.js";
|
|
7
|
+
import "./chunk-TPVMHYHD.js";
|
|
8
|
+
import "./chunk-PXEEWJRV.js";
|
|
9
9
|
export {
|
|
10
10
|
createServer,
|
|
11
11
|
loadConfig
|