@canonry/canonry 4.134.1 → 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/canonry-cli.md +20 -3
- package/assets/assets/{AuditHistoryPanel-BW7LVMSZ.js → AuditHistoryPanel-BS0dmlrQ.js} +1 -1
- package/assets/assets/{BacklinksPage-DU65axM1.js → BacklinksPage-CPpWLVfa.js} +1 -1
- package/assets/assets/{ChartPrimitives-CUZJ7nUb.js → ChartPrimitives-Dv--2i87.js} +1 -1
- package/assets/assets/{HistoryPage-BswdEXC5.js → HistoryPage-BO4Fv-9q.js} +1 -1
- package/assets/assets/{ProjectPage-CttTuKKo.js → ProjectPage-Di_nDqtH.js} +6 -6
- package/assets/assets/{RunRow-CBxbfubI.js → RunRow-BE8zdGJ8.js} +1 -1
- package/assets/assets/{RunsPage-BQxA05ua.js → RunsPage-CbGanhaz.js} +1 -1
- package/assets/assets/{SettingsPage-krEusjc9.js → SettingsPage-odOpsOuf.js} +1 -1
- package/assets/assets/{TrafficPage-DMhcA9lg.js → TrafficPage-DK7oc0DK.js} +1 -1
- package/assets/assets/{TrafficSourceDetailPage-Dm0Gj0HS.js → TrafficSourceDetailPage-CEFjQVuF.js} +1 -1
- package/assets/assets/{arrow-left-_1YaUPbl.js → arrow-left-DgzLEzZB.js} +1 -1
- package/assets/assets/{extract-error-message-D4XKG37U.js → extract-error-message-vlMjpZb2.js} +1 -1
- package/assets/assets/{index-V1C3c7nO.js → index-BMlTgq7D.js} +53 -53
- package/assets/assets/{trash-2-D3LWIGDJ.js → trash-2-DX33Ys-K.js} +1 -1
- package/assets/index.html +1 -1
- package/dist/{chunk-NWVPRV7A.js → chunk-3PFRVEWP.js} +99 -31
- package/dist/{chunk-BSU2MI3Y.js → chunk-PAR6P5H6.js} +1 -1
- package/dist/{chunk-CF5WTWXI.js → chunk-PXEEWJRV.js} +50 -20
- package/dist/{chunk-DVJGFY3J.js → chunk-TPVMHYHD.js} +45 -71
- package/dist/cli.js +18 -25
- package/dist/index.js +4 -4
- package/dist/{intelligence-service-NO4FJUYD.js → intelligence-service-BMEJ5GFZ.js} +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as a}from"./index-
|
|
1
|
+
import{c as a}from"./index-BMlTgq7D.js";const c=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]],d=a("circle-check",c);const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3",key:"1u773s"}],["path",{d:"M12 17h.01",key:"p32p05"}]],k=a("circle-question-mark",e);const t=[["path",{d:"M12 15V3",key:"m9g1x1"}],["path",{d:"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4",key:"ih7n3h"}],["path",{d:"m7 10 5 5 5-5",key:"brsn70"}]],s=a("download",t);const o=[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]],r=a("external-link",o);const n=[["path",{d:"M10 11v6",key:"nco0om"}],["path",{d:"M14 11v6",key:"outv1u"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6",key:"miytrc"}],["path",{d:"M3 6h18",key:"d0wm0j"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2",key:"e791ji"}]],y=a("trash-2",n);export{d as C,s as D,r as E,y as T,k as a};
|
package/assets/index.html
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32.png" />
|
|
13
13
|
<link rel="apple-touch-icon" href="./apple-touch-icon.png" />
|
|
14
14
|
<title>Canonry</title>
|
|
15
|
-
<script type="module" crossorigin src="./assets/index-
|
|
15
|
+
<script type="module" crossorigin src="./assets/index-BMlTgq7D.js"></script>
|
|
16
16
|
<link rel="modulepreload" crossorigin href="./assets/vendor-tanstack-Be8JdV5M.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="./assets/vendor-radix-CQ77EO2y.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="./assets/vendor-recharts-DSxTZhaH.js">
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadConfig,
|
|
11
11
|
loadConfigRaw,
|
|
12
12
|
saveConfigPatch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PAR6P5H6.js";
|
|
14
14
|
import {
|
|
15
15
|
CC_CACHE_DIR,
|
|
16
16
|
DUCKDB_SPEC,
|
|
@@ -119,7 +119,7 @@ import {
|
|
|
119
119
|
siteAuditPages,
|
|
120
120
|
siteAuditSnapshots,
|
|
121
121
|
usageCounters
|
|
122
|
-
} from "./chunk-
|
|
122
|
+
} from "./chunk-TPVMHYHD.js";
|
|
123
123
|
import {
|
|
124
124
|
AGENT_MEMORY_VALUE_MAX_BYTES,
|
|
125
125
|
AGENT_PROVIDER_IDS,
|
|
@@ -171,6 +171,7 @@ import {
|
|
|
171
171
|
effectiveDomains,
|
|
172
172
|
embedClientConfigForRequest,
|
|
173
173
|
factorStatusFromScore,
|
|
174
|
+
formatIsoDateInTimeZone,
|
|
174
175
|
frameAncestorsHeaderValue,
|
|
175
176
|
hostOf,
|
|
176
177
|
isAgentProviderId,
|
|
@@ -193,7 +194,7 @@ import {
|
|
|
193
194
|
validationError,
|
|
194
195
|
winnabilityClassLabel,
|
|
195
196
|
withRetry
|
|
196
|
-
} from "./chunk-
|
|
197
|
+
} from "./chunk-PXEEWJRV.js";
|
|
197
198
|
|
|
198
199
|
// src/telemetry.ts
|
|
199
200
|
import crypto from "crypto";
|
|
@@ -4658,10 +4659,10 @@ async function adsFetch(apiKey, path10, queryPairs = [], method = "GET", body) {
|
|
|
4658
4659
|
throw new OpenAiAdsApiError("OpenAI Ads API returned invalid JSON", 502);
|
|
4659
4660
|
}
|
|
4660
4661
|
}
|
|
4661
|
-
async function fetchAllPages(apiKey, path10, queryPairs) {
|
|
4662
|
+
async function fetchAllPages(apiKey, path10, queryPairs, maxPages = OPENAI_ADS_MAX_PAGES) {
|
|
4662
4663
|
const items = [];
|
|
4663
4664
|
let after = null;
|
|
4664
|
-
for (let page = 0; page <
|
|
4665
|
+
for (let page = 0; page < maxPages; page++) {
|
|
4665
4666
|
const pairs = after ? [...queryPairs, `after=${encodeURIComponent(after)}`] : [...queryPairs];
|
|
4666
4667
|
const response = await adsFetch(apiKey, path10, pairs);
|
|
4667
4668
|
items.push(...response.data);
|
|
@@ -4670,6 +4671,7 @@ async function fetchAllPages(apiKey, path10, queryPairs) {
|
|
|
4670
4671
|
}
|
|
4671
4672
|
after = response.last_id;
|
|
4672
4673
|
}
|
|
4674
|
+
if (maxPages < OPENAI_ADS_MAX_PAGES) return items;
|
|
4673
4675
|
adsClientLog("error", "pagination.cap-reached", { path: path10, pages: OPENAI_ADS_MAX_PAGES, items: items.length });
|
|
4674
4676
|
throw new OpenAiAdsApiError(
|
|
4675
4677
|
`OpenAI Ads API collection remained incomplete after the ${OPENAI_ADS_MAX_PAGES}-page safety cap`,
|
|
@@ -4683,6 +4685,9 @@ function insightsPairs(opts) {
|
|
|
4683
4685
|
...(opts?.timeRanges ?? []).map((range) => `time_ranges[]=${encodeURIComponent(JSON.stringify(range))}`)
|
|
4684
4686
|
];
|
|
4685
4687
|
}
|
|
4688
|
+
function insightsMaxPages(opts) {
|
|
4689
|
+
return opts?.firstPageOnly ? 1 : OPENAI_ADS_MAX_PAGES;
|
|
4690
|
+
}
|
|
4686
4691
|
async function getAdAccount(apiKey) {
|
|
4687
4692
|
validateApiKey(apiKey);
|
|
4688
4693
|
return adsFetch(apiKey, "ad_account");
|
|
@@ -4813,7 +4818,8 @@ async function getCampaignInsights(apiKey, campaignId, opts) {
|
|
|
4813
4818
|
return fetchAllPages(
|
|
4814
4819
|
apiKey,
|
|
4815
4820
|
`campaigns/${encodeURIComponent(campaignId)}/insights`,
|
|
4816
|
-
insightsPairs(opts)
|
|
4821
|
+
insightsPairs(opts),
|
|
4822
|
+
insightsMaxPages(opts)
|
|
4817
4823
|
);
|
|
4818
4824
|
}
|
|
4819
4825
|
async function getAdGroupInsights(apiKey, adGroupId, opts) {
|
|
@@ -4822,7 +4828,8 @@ async function getAdGroupInsights(apiKey, adGroupId, opts) {
|
|
|
4822
4828
|
return fetchAllPages(
|
|
4823
4829
|
apiKey,
|
|
4824
4830
|
`ad_groups/${encodeURIComponent(adGroupId)}/insights`,
|
|
4825
|
-
insightsPairs(opts)
|
|
4831
|
+
insightsPairs(opts),
|
|
4832
|
+
insightsMaxPages(opts)
|
|
4826
4833
|
);
|
|
4827
4834
|
}
|
|
4828
4835
|
|
|
@@ -4862,6 +4869,8 @@ function removeOpenAiAdsConnection(config, projectName) {
|
|
|
4862
4869
|
var log4 = createLogger("AdsSync");
|
|
4863
4870
|
var CAMPAIGN_INSIGHT_FIELDS = ["campaign.impressions", "campaign.clicks", "campaign.spend", "campaign.conversions", "metadata.readable_time"];
|
|
4864
4871
|
var AD_GROUP_INSIGHT_FIELDS = ["ad_group.impressions", "ad_group.clicks", "ad_group.spend", "ad_group.conversions", "metadata.readable_time"];
|
|
4872
|
+
var CAMPAIGN_IN_PROGRESS_INSIGHT_FIELDS = CAMPAIGN_INSIGHT_FIELDS.filter((field) => field !== "campaign.conversions");
|
|
4873
|
+
var AD_GROUP_IN_PROGRESS_INSIGHT_FIELDS = AD_GROUP_INSIGHT_FIELDS.filter((field) => field !== "ad_group.conversions");
|
|
4865
4874
|
var INSIGHTS_LOOKBACK_MS = 90 * 24 * 60 * 60 * 1e3;
|
|
4866
4875
|
function accountHour(date, timezone) {
|
|
4867
4876
|
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
@@ -4879,11 +4888,17 @@ function accountHour(date, timezone) {
|
|
|
4879
4888
|
};
|
|
4880
4889
|
return `${value("year")}-${value("month")}-${value("day")}T${value("hour")}`;
|
|
4881
4890
|
}
|
|
4891
|
+
function accountLocalDate(at, timezone) {
|
|
4892
|
+
return formatIsoDateInTimeZone(at.toISOString(), timezone);
|
|
4893
|
+
}
|
|
4894
|
+
function startOfAccountDay(at, timezone) {
|
|
4895
|
+
return startOfDayHourInTimeZone(accountLocalDate(at, timezone), timezone);
|
|
4896
|
+
}
|
|
4882
4897
|
function trailingAdsInsightHourRange(now, timezone, lookbackMs = INSIGHTS_LOOKBACK_MS) {
|
|
4883
4898
|
return {
|
|
4884
4899
|
type: "hour_range",
|
|
4885
4900
|
since: accountHour(new Date(now.getTime() - lookbackMs), timezone),
|
|
4886
|
-
until:
|
|
4901
|
+
until: startOfAccountDay(now, timezone),
|
|
4887
4902
|
timezone
|
|
4888
4903
|
};
|
|
4889
4904
|
}
|
|
@@ -4891,11 +4906,21 @@ function liveAdsInsightHourRange(request) {
|
|
|
4891
4906
|
return {
|
|
4892
4907
|
type: "hour_range",
|
|
4893
4908
|
since: startOfDayHourInTimeZone(request.startDate, request.timezone),
|
|
4894
|
-
until:
|
|
4909
|
+
until: startOfAccountDay(new Date(request.fetchedAtMs), request.timezone),
|
|
4895
4910
|
timezone: request.timezone
|
|
4896
4911
|
};
|
|
4897
4912
|
}
|
|
4898
|
-
function
|
|
4913
|
+
async function readInsightDays(input) {
|
|
4914
|
+
const [closedDays, unranged] = await Promise.all([
|
|
4915
|
+
input.read({ fields: [...input.rangedFields], timeRanges: [...input.timeRanges] }),
|
|
4916
|
+
input.read({ fields: [...input.inProgressFields], firstPageOnly: true })
|
|
4917
|
+
]);
|
|
4918
|
+
return {
|
|
4919
|
+
closedDays,
|
|
4920
|
+
inProgressDay: unranged.find((row) => row.readable_time === input.inProgressDate) ?? null
|
|
4921
|
+
};
|
|
4922
|
+
}
|
|
4923
|
+
function toInsightUpserts(level, entityId, rows, opts) {
|
|
4899
4924
|
const upserts = [];
|
|
4900
4925
|
for (const row of rows) {
|
|
4901
4926
|
if (!row.readable_time) {
|
|
@@ -4909,11 +4934,22 @@ function toInsightUpserts(level, entityId, rows) {
|
|
|
4909
4934
|
impressions: row.impressions ?? 0,
|
|
4910
4935
|
clicks: row.clicks ?? 0,
|
|
4911
4936
|
spendMicros: dollarsToMicros(row.spend ?? 0),
|
|
4912
|
-
conversions: Math.round(row.conversions ?? 0)
|
|
4937
|
+
conversions: opts.conversionsReported ? Math.round(row.conversions ?? 0) : null
|
|
4913
4938
|
});
|
|
4914
4939
|
}
|
|
4915
4940
|
return upserts;
|
|
4916
4941
|
}
|
|
4942
|
+
function toDailyUpserts(level, entityId, read) {
|
|
4943
|
+
return [
|
|
4944
|
+
...toInsightUpserts(level, entityId, read.closedDays, { conversionsReported: true }),
|
|
4945
|
+
...toInsightUpserts(
|
|
4946
|
+
level,
|
|
4947
|
+
entityId,
|
|
4948
|
+
read.inProgressDay ? [read.inProgressDay] : [],
|
|
4949
|
+
{ conversionsReported: false }
|
|
4950
|
+
)
|
|
4951
|
+
];
|
|
4952
|
+
}
|
|
4917
4953
|
async function executeAdsSync(db, runId, projectId, opts) {
|
|
4918
4954
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4919
4955
|
db.update(runs).set({ status: "running", startedAt: now }).where(eq5(runs.id, runId)).run();
|
|
@@ -4932,7 +4968,9 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
4932
4968
|
log4.info("sync.start", { runId, projectId, adAccountId: connRow.adAccountId });
|
|
4933
4969
|
const account = await getAdAccount(apiKey);
|
|
4934
4970
|
const campaigns = await listCampaigns(apiKey);
|
|
4935
|
-
const
|
|
4971
|
+
const insightAnchor = /* @__PURE__ */ new Date();
|
|
4972
|
+
const insightTimeRanges = [trailingAdsInsightHourRange(insightAnchor, account.timezone)];
|
|
4973
|
+
const inProgressDate = accountLocalDate(insightAnchor, account.timezone);
|
|
4936
4974
|
const errors = /* @__PURE__ */ new Map();
|
|
4937
4975
|
const adGroupsByCampaign = /* @__PURE__ */ new Map();
|
|
4938
4976
|
const adsByGroup = /* @__PURE__ */ new Map();
|
|
@@ -4942,25 +4980,31 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
4942
4980
|
try {
|
|
4943
4981
|
const [adGroups, campaignInsights] = await Promise.all([
|
|
4944
4982
|
listAdGroups(apiKey, campaign.id),
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4983
|
+
readInsightDays({
|
|
4984
|
+
read: (options) => getCampaignInsights(apiKey, campaign.id, options),
|
|
4985
|
+
rangedFields: CAMPAIGN_INSIGHT_FIELDS,
|
|
4986
|
+
inProgressFields: CAMPAIGN_IN_PROGRESS_INSIGHT_FIELDS,
|
|
4987
|
+
timeRanges: insightTimeRanges,
|
|
4988
|
+
inProgressDate
|
|
4948
4989
|
})
|
|
4949
4990
|
]);
|
|
4950
4991
|
const groupResults = await Promise.all(adGroups.map(async (group) => ({
|
|
4951
4992
|
group,
|
|
4952
4993
|
ads: await listAds(apiKey, group.id),
|
|
4953
|
-
insights: await
|
|
4954
|
-
|
|
4955
|
-
|
|
4994
|
+
insights: await readInsightDays({
|
|
4995
|
+
read: (options) => getAdGroupInsights(apiKey, group.id, options),
|
|
4996
|
+
rangedFields: AD_GROUP_INSIGHT_FIELDS,
|
|
4997
|
+
inProgressFields: AD_GROUP_IN_PROGRESS_INSIGHT_FIELDS,
|
|
4998
|
+
timeRanges: insightTimeRanges,
|
|
4999
|
+
inProgressDate
|
|
4956
5000
|
})
|
|
4957
5001
|
})));
|
|
4958
5002
|
syncedCampaigns.push(campaign);
|
|
4959
5003
|
adGroupsByCampaign.set(campaign.id, adGroups);
|
|
4960
|
-
insightUpserts.push(...
|
|
5004
|
+
insightUpserts.push(...toDailyUpserts("campaign", campaign.id, campaignInsights));
|
|
4961
5005
|
for (const { group, ads, insights: insights2 } of groupResults) {
|
|
4962
5006
|
adsByGroup.set(group.id, ads);
|
|
4963
|
-
insightUpserts.push(...
|
|
5007
|
+
insightUpserts.push(...toDailyUpserts("ad_group", group.id, insights2));
|
|
4964
5008
|
}
|
|
4965
5009
|
} catch (err) {
|
|
4966
5010
|
errors.set(campaign.name, err instanceof Error ? err.message : String(err));
|
|
@@ -5029,7 +5073,16 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
5029
5073
|
tx.insert(adsInsightsDaily).values({
|
|
5030
5074
|
id: crypto7.randomUUID(),
|
|
5031
5075
|
projectId,
|
|
5032
|
-
|
|
5076
|
+
level: upsert.level,
|
|
5077
|
+
entityId: upsert.entityId,
|
|
5078
|
+
date: upsert.date,
|
|
5079
|
+
impressions: upsert.impressions,
|
|
5080
|
+
clicks: upsert.clicks,
|
|
5081
|
+
spendMicros: upsert.spendMicros,
|
|
5082
|
+
// A day whose conversions the provider will not report yet starts at
|
|
5083
|
+
// the column default. The first sync after that day closes reads it
|
|
5084
|
+
// from the ranged call and fills it in.
|
|
5085
|
+
conversions: upsert.conversions ?? 0,
|
|
5033
5086
|
syncRunId: runId
|
|
5034
5087
|
}).onConflictDoUpdate({
|
|
5035
5088
|
target: [adsInsightsDaily.projectId, adsInsightsDaily.level, adsInsightsDaily.entityId, adsInsightsDaily.date],
|
|
@@ -5037,7 +5090,10 @@ async function executeAdsSync(db, runId, projectId, opts) {
|
|
|
5037
5090
|
impressions: upsert.impressions,
|
|
5038
5091
|
clicks: upsert.clicks,
|
|
5039
5092
|
spendMicros: upsert.spendMicros,
|
|
5040
|
-
|
|
5093
|
+
// Only written when the provider actually reported a count.
|
|
5094
|
+
// Stamping a placeholder over a stored figure would turn a number
|
|
5095
|
+
// this read could not obtain into a number that is simply wrong.
|
|
5096
|
+
...upsert.conversions === null ? {} : { conversions: upsert.conversions },
|
|
5041
5097
|
syncRunId: runId
|
|
5042
5098
|
}
|
|
5043
5099
|
}).run();
|
|
@@ -7010,7 +7066,7 @@ function readStoredGroundingSources(rawResponse) {
|
|
|
7010
7066
|
return result;
|
|
7011
7067
|
}
|
|
7012
7068
|
async function backfillInsightsCommand(project, opts) {
|
|
7013
|
-
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-
|
|
7069
|
+
const { IntelligenceService: IntelligenceService2 } = await import("./intelligence-service-BMEJ5GFZ.js");
|
|
7014
7070
|
const config = loadConfig();
|
|
7015
7071
|
const db = createClient(config.database);
|
|
7016
7072
|
migrate(db);
|
|
@@ -12246,20 +12302,32 @@ async function createServer(opts) {
|
|
|
12246
12302
|
cpc: row.cpc ?? null,
|
|
12247
12303
|
cpm: row.cpm ?? null
|
|
12248
12304
|
});
|
|
12305
|
+
const adsLiveInsightDays = (read, request, rangedFields, inProgressFields) => readInsightDays({
|
|
12306
|
+
read,
|
|
12307
|
+
rangedFields,
|
|
12308
|
+
inProgressFields,
|
|
12309
|
+
timeRanges: [liveAdsInsightHourRange(request)],
|
|
12310
|
+
inProgressDate: accountLocalDate(new Date(request.fetchedAtMs), request.timezone)
|
|
12311
|
+
});
|
|
12312
|
+
const adsLiveMetricRows = (read) => [...read.closedDays, ...read.inProgressDay ? [read.inProgressDay] : []].map(adsLiveMetricRow);
|
|
12249
12313
|
const adsLiveDeliveryReader = {
|
|
12250
12314
|
listCampaigns: async (apiKey) => (await listCampaigns(apiKey)).map((campaign) => adsLiveEntity(campaign, { mode: campaign.mode })),
|
|
12251
12315
|
listAdGroups: async (apiKey, campaignId) => (await listAdGroups(apiKey, campaignId)).map((adGroup) => adsLiveEntity(adGroup)),
|
|
12252
12316
|
listAds: async (apiKey, adGroupId) => (await listAds(apiKey, adGroupId)).map(
|
|
12253
12317
|
(ad) => adsLiveEntity(ad, { reviewStatus: ad.review_status ?? ad.review?.status ?? null })
|
|
12254
12318
|
),
|
|
12255
|
-
campaignInsights: async (apiKey, campaignId, request) => (await
|
|
12256
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12319
|
+
campaignInsights: async (apiKey, campaignId, request) => adsLiveMetricRows(await adsLiveInsightDays(
|
|
12320
|
+
(options) => getCampaignInsights(apiKey, campaignId, options),
|
|
12321
|
+
request,
|
|
12322
|
+
CAMPAIGN_INSIGHT_FIELDS,
|
|
12323
|
+
CAMPAIGN_IN_PROGRESS_INSIGHT_FIELDS
|
|
12324
|
+
)),
|
|
12325
|
+
adGroupInsights: async (apiKey, adGroupId, request) => adsLiveMetricRows(await adsLiveInsightDays(
|
|
12326
|
+
(options) => getAdGroupInsights(apiKey, adGroupId, options),
|
|
12327
|
+
request,
|
|
12328
|
+
AD_GROUP_INSIGHT_FIELDS,
|
|
12329
|
+
AD_GROUP_IN_PROGRESS_INSIGHT_FIELDS
|
|
12330
|
+
))
|
|
12263
12331
|
};
|
|
12264
12332
|
const scheduler = new Scheduler(opts.db, {
|
|
12265
12333
|
onRunCreated: (runId, projectId, providers2, location) => {
|
|
@@ -3976,7 +3976,21 @@ var ga4AiReferralDtoSchema = z25.object({
|
|
|
3976
3976
|
medium: z25.string(),
|
|
3977
3977
|
trafficClass: aiReferralTrafficClassSchema,
|
|
3978
3978
|
sessions: z25.number(),
|
|
3979
|
-
|
|
3979
|
+
/**
|
|
3980
|
+
* @deprecated Never emitted since 4.135.0. Removed in the next major.
|
|
3981
|
+
*
|
|
3982
|
+
* GA reports `totalUsers` as a COUNT DISTINCT at the grain requested, and
|
|
3983
|
+
* `ga_ai_referrals` is keyed by (date, source, medium, channelGroup,
|
|
3984
|
+
* landingPage, sourceDimension), so summing it re-counted the same visitor on
|
|
3985
|
+
* every extra day, page and channel they appear in. Unlike GA daily users, no
|
|
3986
|
+
* un-dimensioned AI-referral fetch exists to ask Google for the true figure,
|
|
3987
|
+
* so the number could not be corrected — only withdrawn. Optional rather than
|
|
3988
|
+
* deleted so existing API / `canonry ga traffic --format json` / MCP
|
|
3989
|
+
* consumers keep parsing; they now read `undefined` instead of an inflated
|
|
3990
|
+
* number. Sessions are unaffected: GA4 attributes exactly one landing page
|
|
3991
|
+
* per session, so the landing-page rows partition the day and do sum.
|
|
3992
|
+
*/
|
|
3993
|
+
users: z25.number().optional(),
|
|
3980
3994
|
/**
|
|
3981
3995
|
* The winning attribution dimension for this (source, medium) tuple — the
|
|
3982
3996
|
* one with the highest session count. GA4 emits one row per dimension
|
|
@@ -3997,7 +4011,8 @@ var ga4AiReferralLandingPageDtoSchema = z25.object({
|
|
|
3997
4011
|
sourceDimension: ga4SourceDimensionSchema,
|
|
3998
4012
|
landingPage: z25.string(),
|
|
3999
4013
|
sessions: z25.number(),
|
|
4000
|
-
users
|
|
4014
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4015
|
+
users: z25.number().optional()
|
|
4001
4016
|
});
|
|
4002
4017
|
var ga4SocialReferralDtoSchema = z25.object({
|
|
4003
4018
|
source: z25.string(),
|
|
@@ -4037,28 +4052,28 @@ var ga4TrafficSummaryDtoSchema = z25.object({
|
|
|
4037
4052
|
aiReferralLandingPages: z25.array(ga4AiReferralLandingPageDtoSchema),
|
|
4038
4053
|
/** Deduped AI session total: MAX(sessions) per date+source+medium across attribution dimensions, then summed. Cross-cutting: can overlap with Direct/Organic/Social via firstUserSource. */
|
|
4039
4054
|
aiSessionsDeduped: z25.number(),
|
|
4040
|
-
/**
|
|
4041
|
-
aiUsersDeduped: z25.number(),
|
|
4055
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4056
|
+
aiUsersDeduped: z25.number().optional(),
|
|
4042
4057
|
/** Deduped AI sessions whose attribution carries paid intent. */
|
|
4043
4058
|
paidAiSessionsDeduped: z25.number(),
|
|
4044
|
-
/**
|
|
4045
|
-
paidAiUsersDeduped: z25.number(),
|
|
4059
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4060
|
+
paidAiUsersDeduped: z25.number().optional(),
|
|
4046
4061
|
/** Deduped AI sessions without paid intent evidence. */
|
|
4047
4062
|
organicAiSessionsDeduped: z25.number(),
|
|
4048
|
-
/**
|
|
4049
|
-
organicAiUsersDeduped: z25.number(),
|
|
4063
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4064
|
+
organicAiUsersDeduped: z25.number().optional(),
|
|
4050
4065
|
/** AI sessions whose CURRENT sessionSource matched an AI engine. Can overlap with raw Organic/Social/Direct totals; `channelBreakdown` removes those overlaps for display. */
|
|
4051
4066
|
aiSessionsBySession: z25.number(),
|
|
4052
|
-
/**
|
|
4053
|
-
aiUsersBySession: z25.number(),
|
|
4067
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4068
|
+
aiUsersBySession: z25.number().optional(),
|
|
4054
4069
|
/** Session-source-only paid AI sessions. */
|
|
4055
4070
|
paidAiSessionsBySession: z25.number(),
|
|
4056
|
-
/**
|
|
4057
|
-
paidAiUsersBySession: z25.number(),
|
|
4071
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4072
|
+
paidAiUsersBySession: z25.number().optional(),
|
|
4058
4073
|
/** Session-source-only organic/non-paid AI sessions. */
|
|
4059
4074
|
organicAiSessionsBySession: z25.number(),
|
|
4060
|
-
/**
|
|
4061
|
-
organicAiUsersBySession: z25.number(),
|
|
4075
|
+
/** @deprecated See `GA4AiReferralDto.users`. Never emitted since 4.135.0. */
|
|
4076
|
+
organicAiUsersBySession: z25.number().optional(),
|
|
4062
4077
|
socialReferrals: z25.array(ga4SocialReferralDtoSchema),
|
|
4063
4078
|
/** Total social sessions (session-scoped, no cross-dimension dedup needed). */
|
|
4064
4079
|
socialSessions: z25.number(),
|
|
@@ -6841,13 +6856,31 @@ var adsInsightRowDtoSchema = z38.object({
|
|
|
6841
6856
|
/** clicks / impressions; null when impressions is 0. */
|
|
6842
6857
|
ctr: z38.number().nullable(),
|
|
6843
6858
|
/** spendMicros / clicks, rounded to integer micros; null when clicks is 0. */
|
|
6844
|
-
cpcMicros: z38.number().int().nullable()
|
|
6859
|
+
cpcMicros: z38.number().int().nullable(),
|
|
6860
|
+
/**
|
|
6861
|
+
* True when `date` is the ad account's CURRENT local calendar date, so this
|
|
6862
|
+
* row is a running figure rather than a closed day. The sync re-reads the
|
|
6863
|
+
* open day and overwrites the row every time it runs, so the numbers here
|
|
6864
|
+
* keep rising until the day ends. Do not compare it against a finished day
|
|
6865
|
+
* or treat it as final.
|
|
6866
|
+
*
|
|
6867
|
+
* `conversions` is the one field that does NOT fill in live on such a row.
|
|
6868
|
+
* The provider serves the open day only from a call that may not request
|
|
6869
|
+
* conversion metrics, so the count stays at 0 until the day closes and the
|
|
6870
|
+
* next sync reads the real figure. Treat it as not yet reported.
|
|
6871
|
+
*/
|
|
6872
|
+
inProgress: z38.boolean()
|
|
6845
6873
|
});
|
|
6846
6874
|
var adsInsightsResponseSchema = z38.object({
|
|
6847
6875
|
rows: z38.array(adsInsightRowDtoSchema),
|
|
6848
6876
|
/** Account currency for rendering spend/cpc; null before the first sync. */
|
|
6849
6877
|
currencyCode: z38.string().nullable().optional()
|
|
6850
6878
|
});
|
|
6879
|
+
var adsRollupWindowDtoSchema = z38.object({
|
|
6880
|
+
from: z38.string().nullable(),
|
|
6881
|
+
to: z38.string().nullable(),
|
|
6882
|
+
inProgressDate: z38.string().nullable()
|
|
6883
|
+
});
|
|
6851
6884
|
var adsTotalsDtoSchema = z38.object({
|
|
6852
6885
|
impressions: z38.number().int(),
|
|
6853
6886
|
clicks: z38.number().int(),
|
|
@@ -6865,10 +6898,7 @@ var adsSummaryDtoSchema = z38.object({
|
|
|
6865
6898
|
adGroupCount: z38.number().int(),
|
|
6866
6899
|
adCount: z38.number().int(),
|
|
6867
6900
|
/** Date range the totals cover (oldest/newest rollup date), null when empty. */
|
|
6868
|
-
window:
|
|
6869
|
-
from: z38.string().nullable(),
|
|
6870
|
-
to: z38.string().nullable()
|
|
6871
|
-
}),
|
|
6901
|
+
window: adsRollupWindowDtoSchema,
|
|
6872
6902
|
/** Campaign-level rollup totals over the window (levels are not summed across). */
|
|
6873
6903
|
totals: adsTotalsDtoSchema
|
|
6874
6904
|
});
|
|
@@ -6941,7 +6971,7 @@ var adsDeliveryDiagnosticsDtoSchema = z38.object({
|
|
|
6941
6971
|
}),
|
|
6942
6972
|
historicalCampaignRollups: z38.object({
|
|
6943
6973
|
status: adsHistoricalCampaignRollupStatusSchema,
|
|
6944
|
-
window:
|
|
6974
|
+
window: adsRollupWindowDtoSchema,
|
|
6945
6975
|
totals: adsTotalsDtoSchema.nullable()
|
|
6946
6976
|
}),
|
|
6947
6977
|
storedConfiguration: z38.object({
|