@ainyc/canonry 1.45.3 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/assets/index-Cxg_4UWs.js +282 -0
- package/assets/index.html +1 -1
- package/dist/{chunk-WNOUK4KA.js → chunk-22RIKNII.js} +66 -30
- package/dist/cli.js +98 -31
- package/dist/index.js +1 -1
- package/package.json +8 -8
- package/assets/assets/index-BR8Krvpj.js +0 -282
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-Cxg_4UWs.js"></script>
|
|
16
16
|
<link rel="stylesheet" crossorigin href="./assets/index--ev1Bjls.css">
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -997,6 +997,17 @@ var scheduleUpsertRequestSchema = z10.object({
|
|
|
997
997
|
import { z as z11 } from "zod";
|
|
998
998
|
var visibilityMetricModeSchema = z11.enum(["answer", "citation"]);
|
|
999
999
|
var VisibilityMetricModes = visibilityMetricModeSchema.enum;
|
|
1000
|
+
function parseWindow(value) {
|
|
1001
|
+
if (value === "7d" || value === "30d" || value === "90d" || value === "all") return value;
|
|
1002
|
+
return "all";
|
|
1003
|
+
}
|
|
1004
|
+
function windowCutoff(window) {
|
|
1005
|
+
if (window === "all") return null;
|
|
1006
|
+
const days = window === "7d" ? 7 : window === "30d" ? 30 : 90;
|
|
1007
|
+
const d = /* @__PURE__ */ new Date();
|
|
1008
|
+
d.setDate(d.getDate() - days);
|
|
1009
|
+
return d.toISOString();
|
|
1010
|
+
}
|
|
1000
1011
|
|
|
1001
1012
|
// ../contracts/src/source-categories.ts
|
|
1002
1013
|
var SOURCE_CATEGORY_RULES = [
|
|
@@ -3143,17 +3154,6 @@ function parseGroundingSources(rawResponse) {
|
|
|
3143
3154
|
(s) => typeof s.uri === "string" && !isProviderInfraDomain(s.uri)
|
|
3144
3155
|
);
|
|
3145
3156
|
}
|
|
3146
|
-
function parseWindow(value) {
|
|
3147
|
-
if (value === "7d" || value === "30d" || value === "90d" || value === "all") return value;
|
|
3148
|
-
return "all";
|
|
3149
|
-
}
|
|
3150
|
-
function windowCutoff(window) {
|
|
3151
|
-
if (window === "all") return null;
|
|
3152
|
-
const days = window === "7d" ? 7 : window === "30d" ? 30 : 90;
|
|
3153
|
-
const d = /* @__PURE__ */ new Date();
|
|
3154
|
-
d.setDate(d.getDate() - days);
|
|
3155
|
-
return d.toISOString();
|
|
3156
|
-
}
|
|
3157
3157
|
function bucketSizeForSpan(spanDays) {
|
|
3158
3158
|
if (spanDays <= 14) return 1;
|
|
3159
3159
|
if (spanDays <= 60) return 7;
|
|
@@ -4506,7 +4506,8 @@ var routeCatalog = [
|
|
|
4506
4506
|
{ name: "endDate", in: "query", description: "Filter by end date.", schema: stringSchema },
|
|
4507
4507
|
{ name: "query", in: "query", description: "Filter by search query.", schema: stringSchema },
|
|
4508
4508
|
{ name: "page", in: "query", description: "Filter by page URL.", schema: stringSchema },
|
|
4509
|
-
limitQueryParameter
|
|
4509
|
+
limitQueryParameter,
|
|
4510
|
+
analyticsWindowParameter
|
|
4510
4511
|
],
|
|
4511
4512
|
responses: {
|
|
4512
4513
|
200: { description: "GSC performance rows returned." },
|
|
@@ -5332,7 +5333,7 @@ var routeCatalog = [
|
|
|
5332
5333
|
path: "/api/v1/projects/{name}/ga/traffic",
|
|
5333
5334
|
summary: "Get GA4 landing page traffic and AI referral sources",
|
|
5334
5335
|
tags: ["ga4"],
|
|
5335
|
-
parameters: [nameParameter, limitQueryParameter],
|
|
5336
|
+
parameters: [nameParameter, limitQueryParameter, analyticsWindowParameter],
|
|
5336
5337
|
responses: {
|
|
5337
5338
|
200: { description: "GA4 traffic data returned." },
|
|
5338
5339
|
400: { description: "GA4 is not connected." },
|
|
@@ -5344,7 +5345,7 @@ var routeCatalog = [
|
|
|
5344
5345
|
path: "/api/v1/projects/{name}/ga/ai-referral-history",
|
|
5345
5346
|
summary: "Get AI referral sessions per day grouped by source",
|
|
5346
5347
|
tags: ["ga4"],
|
|
5347
|
-
parameters: [nameParameter],
|
|
5348
|
+
parameters: [nameParameter, analyticsWindowParameter],
|
|
5348
5349
|
responses: {
|
|
5349
5350
|
200: { description: "AI referral history returned." },
|
|
5350
5351
|
400: { description: "GA4 is not connected." },
|
|
@@ -5356,7 +5357,7 @@ var routeCatalog = [
|
|
|
5356
5357
|
path: "/api/v1/projects/{name}/ga/social-referral-history",
|
|
5357
5358
|
summary: "Get social media referral sessions per day grouped by source",
|
|
5358
5359
|
tags: ["ga4"],
|
|
5359
|
-
parameters: [nameParameter],
|
|
5360
|
+
parameters: [nameParameter, analyticsWindowParameter],
|
|
5360
5361
|
responses: {
|
|
5361
5362
|
200: { description: "Social referral history returned." },
|
|
5362
5363
|
400: { description: "GA4 is not connected." },
|
|
@@ -5392,7 +5393,7 @@ var routeCatalog = [
|
|
|
5392
5393
|
path: "/api/v1/projects/{name}/ga/session-history",
|
|
5393
5394
|
summary: "Get total sessions per day for the project",
|
|
5394
5395
|
tags: ["ga4"],
|
|
5395
|
-
parameters: [nameParameter],
|
|
5396
|
+
parameters: [nameParameter, analyticsWindowParameter],
|
|
5396
5397
|
responses: {
|
|
5397
5398
|
200: { description: "Session history returned." },
|
|
5398
5399
|
400: { description: "GA4 is not connected." },
|
|
@@ -7050,8 +7051,10 @@ async function googleRoutes(app, opts) {
|
|
|
7050
7051
|
app.get("/projects/:name/google/gsc/performance", async (request) => {
|
|
7051
7052
|
const project = resolveProject(app.db, request.params.name);
|
|
7052
7053
|
const { startDate, endDate, query, page, limit } = request.query;
|
|
7054
|
+
const cutoffDate = !startDate ? windowCutoff(parseWindow(request.query.window))?.slice(0, 10) ?? null : null;
|
|
7053
7055
|
const conditions = [eq14(gscSearchData.projectId, project.id)];
|
|
7054
7056
|
if (startDate) conditions.push(sql2`${gscSearchData.date} >= ${startDate}`);
|
|
7057
|
+
else if (cutoffDate) conditions.push(sql2`${gscSearchData.date} >= ${cutoffDate}`);
|
|
7055
7058
|
if (endDate) conditions.push(sql2`${gscSearchData.date} <= ${endDate}`);
|
|
7056
7059
|
if (query) conditions.push(sql2`${gscSearchData.query} LIKE ${"%" + query + "%"}`);
|
|
7057
7060
|
if (page) conditions.push(sql2`${gscSearchData.page} LIKE ${"%" + page + "%"}`);
|
|
@@ -8629,24 +8632,41 @@ async function ga4Routes(app, opts) {
|
|
|
8629
8632
|
const project = resolveProject(app.db, request.params.name);
|
|
8630
8633
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
8631
8634
|
const limit = Math.max(1, Math.min(parseInt(request.query.limit ?? "50", 10) || 50, 500));
|
|
8632
|
-
const
|
|
8635
|
+
const window = parseWindow(request.query.window);
|
|
8636
|
+
const cutoff = windowCutoff(window);
|
|
8637
|
+
const cutoffDate = cutoff?.slice(0, 10) ?? null;
|
|
8638
|
+
const snapshotConditions = [eq17(gaTrafficSnapshots.projectId, project.id)];
|
|
8639
|
+
if (cutoffDate) snapshotConditions.push(sql3`${gaTrafficSnapshots.date} >= ${cutoffDate}`);
|
|
8640
|
+
const aiConditions = [eq17(gaAiReferrals.projectId, project.id)];
|
|
8641
|
+
if (cutoffDate) aiConditions.push(sql3`${gaAiReferrals.date} >= ${cutoffDate}`);
|
|
8642
|
+
const socialConditions = [eq17(gaSocialReferrals.projectId, project.id)];
|
|
8643
|
+
if (cutoffDate) socialConditions.push(sql3`${gaSocialReferrals.date} >= ${cutoffDate}`);
|
|
8644
|
+
const summaryRow = cutoffDate ? app.db.select({
|
|
8645
|
+
totalSessions: sql3`COALESCE(SUM(${gaTrafficSnapshots.sessions}), 0)`,
|
|
8646
|
+
totalOrganicSessions: sql3`COALESCE(SUM(${gaTrafficSnapshots.organicSessions}), 0)`,
|
|
8647
|
+
totalUsers: sql3`COALESCE(SUM(${gaTrafficSnapshots.users}), 0)`
|
|
8648
|
+
}).from(gaTrafficSnapshots).where(and6(...snapshotConditions)).get() : app.db.select({
|
|
8633
8649
|
totalSessions: gaTrafficSummaries.totalSessions,
|
|
8634
8650
|
totalOrganicSessions: gaTrafficSummaries.totalOrganicSessions,
|
|
8635
8651
|
totalUsers: gaTrafficSummaries.totalUsers
|
|
8636
8652
|
}).from(gaTrafficSummaries).where(eq17(gaTrafficSummaries.projectId, project.id)).get();
|
|
8653
|
+
const summaryMeta = app.db.select({
|
|
8654
|
+
periodStart: gaTrafficSummaries.periodStart,
|
|
8655
|
+
periodEnd: gaTrafficSummaries.periodEnd
|
|
8656
|
+
}).from(gaTrafficSummaries).where(eq17(gaTrafficSummaries.projectId, project.id)).get();
|
|
8637
8657
|
const rows = app.db.select({
|
|
8638
8658
|
landingPage: gaTrafficSnapshots.landingPage,
|
|
8639
8659
|
sessions: sql3`SUM(${gaTrafficSnapshots.sessions})`,
|
|
8640
8660
|
organicSessions: sql3`SUM(${gaTrafficSnapshots.organicSessions})`,
|
|
8641
8661
|
users: sql3`SUM(${gaTrafficSnapshots.users})`
|
|
8642
|
-
}).from(gaTrafficSnapshots).where(
|
|
8662
|
+
}).from(gaTrafficSnapshots).where(and6(...snapshotConditions)).groupBy(gaTrafficSnapshots.landingPage).orderBy(sql3`SUM(${gaTrafficSnapshots.sessions}) DESC`).limit(limit).all();
|
|
8643
8663
|
const aiReferrals = app.db.select({
|
|
8644
8664
|
source: gaAiReferrals.source,
|
|
8645
8665
|
medium: gaAiReferrals.medium,
|
|
8646
8666
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
8647
8667
|
sessions: sql3`SUM(${gaAiReferrals.sessions})`,
|
|
8648
8668
|
users: sql3`SUM(${gaAiReferrals.users})`
|
|
8649
|
-
}).from(gaAiReferrals).where(
|
|
8669
|
+
}).from(gaAiReferrals).where(and6(...aiConditions)).groupBy(gaAiReferrals.source, gaAiReferrals.medium, gaAiReferrals.sourceDimension).orderBy(sql3`SUM(${gaAiReferrals.sessions}) DESC`).all();
|
|
8650
8670
|
const aiDeduped = app.db.select({
|
|
8651
8671
|
sessions: sql3`SUM(max_sessions)`,
|
|
8652
8672
|
users: sql3`SUM(max_users)`
|
|
@@ -8656,7 +8676,7 @@ async function ga4Routes(app, opts) {
|
|
|
8656
8676
|
MAX(sessions) AS max_sessions,
|
|
8657
8677
|
MAX(users) AS max_users
|
|
8658
8678
|
FROM ga_ai_referrals
|
|
8659
|
-
WHERE project_id = ${project.id}
|
|
8679
|
+
WHERE project_id = ${project.id}${cutoffDate ? sql3` AND date >= ${cutoffDate}` : sql3``}
|
|
8660
8680
|
GROUP BY date, source, medium
|
|
8661
8681
|
)`
|
|
8662
8682
|
).get();
|
|
@@ -8666,17 +8686,17 @@ async function ga4Routes(app, opts) {
|
|
|
8666
8686
|
channelGroup: gaSocialReferrals.channelGroup,
|
|
8667
8687
|
sessions: sql3`SUM(${gaSocialReferrals.sessions})`,
|
|
8668
8688
|
users: sql3`SUM(${gaSocialReferrals.users})`
|
|
8669
|
-
}).from(gaSocialReferrals).where(
|
|
8689
|
+
}).from(gaSocialReferrals).where(and6(...socialConditions)).groupBy(gaSocialReferrals.source, gaSocialReferrals.medium, gaSocialReferrals.channelGroup).orderBy(sql3`SUM(${gaSocialReferrals.sessions}) DESC`).all();
|
|
8670
8690
|
const socialTotals = app.db.select({
|
|
8671
8691
|
sessions: sql3`SUM(${gaSocialReferrals.sessions})`,
|
|
8672
8692
|
users: sql3`SUM(${gaSocialReferrals.users})`
|
|
8673
|
-
}).from(gaSocialReferrals).where(
|
|
8693
|
+
}).from(gaSocialReferrals).where(and6(...socialConditions)).get();
|
|
8674
8694
|
const latestSync = app.db.select({ syncedAt: gaTrafficSummaries.syncedAt }).from(gaTrafficSummaries).where(eq17(gaTrafficSummaries.projectId, project.id)).orderBy(desc7(gaTrafficSummaries.syncedAt)).limit(1).get();
|
|
8675
|
-
const total =
|
|
8695
|
+
const total = summaryRow?.totalSessions ?? 0;
|
|
8676
8696
|
return {
|
|
8677
8697
|
totalSessions: total,
|
|
8678
|
-
totalOrganicSessions:
|
|
8679
|
-
totalUsers:
|
|
8698
|
+
totalOrganicSessions: summaryRow?.totalOrganicSessions ?? 0,
|
|
8699
|
+
totalUsers: summaryRow?.totalUsers ?? 0,
|
|
8680
8700
|
topPages: rows.map((r) => ({
|
|
8681
8701
|
landingPage: r.landingPage,
|
|
8682
8702
|
sessions: r.sessions ?? 0,
|
|
@@ -8701,15 +8721,25 @@ async function ga4Routes(app, opts) {
|
|
|
8701
8721
|
})),
|
|
8702
8722
|
socialSessions: socialTotals?.sessions ?? 0,
|
|
8703
8723
|
socialUsers: socialTotals?.users ?? 0,
|
|
8704
|
-
organicSharePct: total > 0 ? Math.round((
|
|
8724
|
+
organicSharePct: total > 0 ? Math.round((summaryRow?.totalOrganicSessions ?? 0) / total * 100) : 0,
|
|
8705
8725
|
aiSharePct: total > 0 ? Math.round((aiDeduped?.sessions ?? 0) / total * 100) : 0,
|
|
8706
8726
|
socialSharePct: total > 0 ? Math.round((socialTotals?.sessions ?? 0) / total * 100) : 0,
|
|
8707
|
-
lastSyncedAt: latestSync?.syncedAt ?? null
|
|
8727
|
+
lastSyncedAt: latestSync?.syncedAt ?? null,
|
|
8728
|
+
periodStart: (() => {
|
|
8729
|
+
const start = cutoffDate ?? summaryMeta?.periodStart ?? null;
|
|
8730
|
+
const end = summaryMeta?.periodEnd ?? null;
|
|
8731
|
+
if (start && end && start > end) return summaryMeta?.periodStart ?? null;
|
|
8732
|
+
return start;
|
|
8733
|
+
})(),
|
|
8734
|
+
periodEnd: summaryMeta?.periodEnd ?? null
|
|
8708
8735
|
};
|
|
8709
8736
|
});
|
|
8710
8737
|
app.get("/projects/:name/ga/ai-referral-history", async (request, _reply) => {
|
|
8711
8738
|
const project = resolveProject(app.db, request.params.name);
|
|
8712
8739
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
8740
|
+
const cutoffDate = windowCutoff(parseWindow(request.query.window))?.slice(0, 10) ?? null;
|
|
8741
|
+
const conditions = [eq17(gaAiReferrals.projectId, project.id)];
|
|
8742
|
+
if (cutoffDate) conditions.push(sql3`${gaAiReferrals.date} >= ${cutoffDate}`);
|
|
8713
8743
|
const rows = app.db.select({
|
|
8714
8744
|
date: gaAiReferrals.date,
|
|
8715
8745
|
source: gaAiReferrals.source,
|
|
@@ -8717,12 +8747,15 @@ async function ga4Routes(app, opts) {
|
|
|
8717
8747
|
sourceDimension: gaAiReferrals.sourceDimension,
|
|
8718
8748
|
sessions: gaAiReferrals.sessions,
|
|
8719
8749
|
users: gaAiReferrals.users
|
|
8720
|
-
}).from(gaAiReferrals).where(
|
|
8750
|
+
}).from(gaAiReferrals).where(and6(...conditions)).orderBy(gaAiReferrals.date).all();
|
|
8721
8751
|
return rows;
|
|
8722
8752
|
});
|
|
8723
8753
|
app.get("/projects/:name/ga/social-referral-history", async (request, _reply) => {
|
|
8724
8754
|
const project = resolveProject(app.db, request.params.name);
|
|
8725
8755
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
8756
|
+
const cutoffDate = windowCutoff(parseWindow(request.query.window))?.slice(0, 10) ?? null;
|
|
8757
|
+
const conditions = [eq17(gaSocialReferrals.projectId, project.id)];
|
|
8758
|
+
if (cutoffDate) conditions.push(sql3`${gaSocialReferrals.date} >= ${cutoffDate}`);
|
|
8726
8759
|
const rows = app.db.select({
|
|
8727
8760
|
date: gaSocialReferrals.date,
|
|
8728
8761
|
source: gaSocialReferrals.source,
|
|
@@ -8730,7 +8763,7 @@ async function ga4Routes(app, opts) {
|
|
|
8730
8763
|
channelGroup: gaSocialReferrals.channelGroup,
|
|
8731
8764
|
sessions: gaSocialReferrals.sessions,
|
|
8732
8765
|
users: gaSocialReferrals.users
|
|
8733
|
-
}).from(gaSocialReferrals).where(
|
|
8766
|
+
}).from(gaSocialReferrals).where(and6(...conditions)).orderBy(gaSocialReferrals.date).all();
|
|
8734
8767
|
return rows;
|
|
8735
8768
|
});
|
|
8736
8769
|
app.get("/projects/:name/ga/social-referral-trend", async (request, _reply) => {
|
|
@@ -8863,12 +8896,15 @@ async function ga4Routes(app, opts) {
|
|
|
8863
8896
|
app.get("/projects/:name/ga/session-history", async (request, _reply) => {
|
|
8864
8897
|
const project = resolveProject(app.db, request.params.name);
|
|
8865
8898
|
requireGa4Connection(opts, project.name, project.canonicalDomain);
|
|
8899
|
+
const cutoffDate = windowCutoff(parseWindow(request.query.window))?.slice(0, 10) ?? null;
|
|
8900
|
+
const conditions = [eq17(gaTrafficSnapshots.projectId, project.id)];
|
|
8901
|
+
if (cutoffDate) conditions.push(sql3`${gaTrafficSnapshots.date} >= ${cutoffDate}`);
|
|
8866
8902
|
const rows = app.db.select({
|
|
8867
8903
|
date: gaTrafficSnapshots.date,
|
|
8868
8904
|
sessions: sql3`SUM(${gaTrafficSnapshots.sessions})`,
|
|
8869
8905
|
organicSessions: sql3`SUM(${gaTrafficSnapshots.organicSessions})`,
|
|
8870
8906
|
users: sql3`SUM(${gaTrafficSnapshots.users})`
|
|
8871
|
-
}).from(gaTrafficSnapshots).where(
|
|
8907
|
+
}).from(gaTrafficSnapshots).where(and6(...conditions)).groupBy(gaTrafficSnapshots.date).orderBy(gaTrafficSnapshots.date).all();
|
|
8872
8908
|
return rows.map((r) => ({
|
|
8873
8909
|
date: r.date,
|
|
8874
8910
|
sessions: r.sessions ?? 0,
|
package/dist/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
setGoogleAuthConfig,
|
|
29
29
|
showFirstRunNotice,
|
|
30
30
|
trackEvent
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-22RIKNII.js";
|
|
32
32
|
import {
|
|
33
33
|
apiKeys,
|
|
34
34
|
competitors,
|
|
@@ -909,11 +909,13 @@ var ApiClient = class {
|
|
|
909
909
|
async gaCoverage(project) {
|
|
910
910
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/coverage`);
|
|
911
911
|
}
|
|
912
|
-
async gaAiReferralHistory(project) {
|
|
913
|
-
|
|
912
|
+
async gaAiReferralHistory(project, params) {
|
|
913
|
+
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
914
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/ai-referral-history${qs}`);
|
|
914
915
|
}
|
|
915
|
-
async gaSocialReferralHistory(project) {
|
|
916
|
-
|
|
916
|
+
async gaSocialReferralHistory(project, params) {
|
|
917
|
+
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
918
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-history${qs}`);
|
|
917
919
|
}
|
|
918
920
|
async gaSocialReferralTrend(project) {
|
|
919
921
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-trend`);
|
|
@@ -921,8 +923,9 @@ var ApiClient = class {
|
|
|
921
923
|
async gaAttributionTrend(project) {
|
|
922
924
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/attribution-trend`);
|
|
923
925
|
}
|
|
924
|
-
async gaSessionHistory(project) {
|
|
925
|
-
|
|
926
|
+
async gaSessionHistory(project, params) {
|
|
927
|
+
const qs = params ? "?" + new URLSearchParams(params).toString() : "";
|
|
928
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/session-history${qs}`);
|
|
926
929
|
}
|
|
927
930
|
async wordpressConnect(project, body) {
|
|
928
931
|
return this.request("POST", `/projects/${encodeURIComponent(project)}/wordpress/connect`, body);
|
|
@@ -1781,13 +1784,18 @@ async function gaTraffic(project, opts) {
|
|
|
1781
1784
|
const client = getClient3();
|
|
1782
1785
|
const params = {};
|
|
1783
1786
|
if (opts?.limit) params.limit = String(opts.limit);
|
|
1787
|
+
if (opts?.window) params.window = opts.window;
|
|
1784
1788
|
const result = await client.gaTraffic(project, Object.keys(params).length > 0 ? params : void 0);
|
|
1785
1789
|
if (opts?.format === "json") {
|
|
1786
1790
|
console.log(JSON.stringify(result, null, 2));
|
|
1787
1791
|
return;
|
|
1788
1792
|
}
|
|
1789
1793
|
if (result.topPages.length === 0 && result.aiReferrals.length === 0 && result.socialReferrals.length === 0) {
|
|
1790
|
-
|
|
1794
|
+
if (!result.lastSyncedAt) {
|
|
1795
|
+
console.log('No GA4 traffic data. Run "canonry ga sync <project>" first.');
|
|
1796
|
+
} else {
|
|
1797
|
+
console.log(`No GA4 traffic data for the selected period.${opts?.window ? ` Try a wider window or omit --window.` : ""}`);
|
|
1798
|
+
}
|
|
1791
1799
|
return;
|
|
1792
1800
|
}
|
|
1793
1801
|
console.log(`GA4 Traffic for "${project}"
|
|
@@ -1847,15 +1855,15 @@ async function gaTraffic(project, opts) {
|
|
|
1847
1855
|
Last synced: ${result.lastSyncedAt}`);
|
|
1848
1856
|
}
|
|
1849
1857
|
}
|
|
1850
|
-
async function gaAiReferralHistory(project,
|
|
1858
|
+
async function gaAiReferralHistory(project, opts) {
|
|
1851
1859
|
const client = getClient3();
|
|
1852
|
-
const result = await client.gaAiReferralHistory(project);
|
|
1853
|
-
if (format === "json") {
|
|
1860
|
+
const result = await client.gaAiReferralHistory(project, opts?.window ? { window: opts.window } : void 0);
|
|
1861
|
+
if (opts?.format === "json") {
|
|
1854
1862
|
console.log(JSON.stringify(result, null, 2));
|
|
1855
1863
|
return;
|
|
1856
1864
|
}
|
|
1857
1865
|
if (result.length === 0) {
|
|
1858
|
-
console.log(
|
|
1866
|
+
console.log(`No AI referral history.${opts?.window ? " Try a wider window or omit --window." : ' Run "canonry ga sync <project>" first.'}`);
|
|
1859
1867
|
return;
|
|
1860
1868
|
}
|
|
1861
1869
|
const dateWidth = 12;
|
|
@@ -1872,15 +1880,15 @@ async function gaAiReferralHistory(project, format) {
|
|
|
1872
1880
|
);
|
|
1873
1881
|
}
|
|
1874
1882
|
}
|
|
1875
|
-
async function gaSocialReferralHistory(project,
|
|
1883
|
+
async function gaSocialReferralHistory(project, opts) {
|
|
1876
1884
|
const client = getClient3();
|
|
1877
|
-
const result = await client.gaSocialReferralHistory(project);
|
|
1878
|
-
if (format === "json") {
|
|
1885
|
+
const result = await client.gaSocialReferralHistory(project, opts?.window ? { window: opts.window } : void 0);
|
|
1886
|
+
if (opts?.format === "json") {
|
|
1879
1887
|
console.log(JSON.stringify(result, null, 2));
|
|
1880
1888
|
return;
|
|
1881
1889
|
}
|
|
1882
1890
|
if (result.length === 0) {
|
|
1883
|
-
console.log(
|
|
1891
|
+
console.log(`No social referral history.${opts?.window ? " Try a wider window or omit --window." : ' Run "canonry ga sync <project>" first.'}`);
|
|
1884
1892
|
return;
|
|
1885
1893
|
}
|
|
1886
1894
|
const dateWidth = 12;
|
|
@@ -1897,6 +1905,28 @@ async function gaSocialReferralHistory(project, format) {
|
|
|
1897
1905
|
);
|
|
1898
1906
|
}
|
|
1899
1907
|
}
|
|
1908
|
+
async function gaSessionHistory(project, opts) {
|
|
1909
|
+
const client = getClient3();
|
|
1910
|
+
const result = await client.gaSessionHistory(project, opts?.window ? { window: opts.window } : void 0);
|
|
1911
|
+
if (opts?.format === "json") {
|
|
1912
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
if (result.length === 0) {
|
|
1916
|
+
console.log(`No session history.${opts?.window ? " Try a wider window or omit --window." : ' Run "canonry ga sync <project>" first.'}`);
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
const dateWidth = 12;
|
|
1920
|
+
console.log(`GA4 Session History for "${project}":
|
|
1921
|
+
`);
|
|
1922
|
+
console.log(` ${"DATE".padEnd(dateWidth)} ${"SESSIONS".padEnd(10)}${"ORGANIC".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1923
|
+
console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1924
|
+
for (const row of result) {
|
|
1925
|
+
console.log(
|
|
1926
|
+
` ${row.date.padEnd(dateWidth)} ${String(row.sessions).padEnd(10)}${String(row.organicSessions).padEnd(10)}${String(row.users).padEnd(8)}`
|
|
1927
|
+
);
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1900
1930
|
async function gaCoverage(project, format) {
|
|
1901
1931
|
const client = getClient3();
|
|
1902
1932
|
const result = await client.gaCoverage(project);
|
|
@@ -2034,9 +2064,12 @@ async function gaAttribution(project, opts) {
|
|
|
2034
2064
|
const m = trend.socialBiggestMover;
|
|
2035
2065
|
console.log(` Social Mover: ${m.source} (${m.changePct >= 0 ? "+" : ""}${m.changePct}%, ${m.sessionsPrev7d}\u2192${m.sessions7d} sessions/7d)`);
|
|
2036
2066
|
}
|
|
2037
|
-
if (traffic.
|
|
2067
|
+
if (traffic.periodStart && traffic.periodEnd) {
|
|
2038
2068
|
console.log(`
|
|
2039
|
-
|
|
2069
|
+
Period: ${traffic.periodStart} to ${traffic.periodEnd}`);
|
|
2070
|
+
}
|
|
2071
|
+
if (traffic.lastSyncedAt) {
|
|
2072
|
+
console.log(` Last synced: ${traffic.lastSyncedAt}`);
|
|
2040
2073
|
}
|
|
2041
2074
|
return;
|
|
2042
2075
|
}
|
|
@@ -2053,7 +2086,9 @@ async function gaAttribution(project, opts) {
|
|
|
2053
2086
|
socialSharePct: traffic.socialSharePct,
|
|
2054
2087
|
organicSharePct: traffic.organicSharePct,
|
|
2055
2088
|
aiReferrals: traffic.aiReferrals,
|
|
2056
|
-
socialReferrals: traffic.socialReferrals
|
|
2089
|
+
socialReferrals: traffic.socialReferrals,
|
|
2090
|
+
periodStart: traffic.periodStart,
|
|
2091
|
+
periodEnd: traffic.periodEnd
|
|
2057
2092
|
}, null, 2));
|
|
2058
2093
|
return;
|
|
2059
2094
|
}
|
|
@@ -2091,9 +2126,12 @@ async function gaAttribution(project, opts) {
|
|
|
2091
2126
|
console.log(` ${ref.source.padEnd(25)} ${String(ref.sessions).padEnd(8)} sessions (${chanLabel})`);
|
|
2092
2127
|
}
|
|
2093
2128
|
}
|
|
2094
|
-
if (traffic.
|
|
2129
|
+
if (traffic.periodStart && traffic.periodEnd) {
|
|
2095
2130
|
console.log(`
|
|
2096
|
-
|
|
2131
|
+
Period: ${traffic.periodStart} to ${traffic.periodEnd}`);
|
|
2132
|
+
}
|
|
2133
|
+
if (traffic.lastSyncedAt) {
|
|
2134
|
+
console.log(` Last synced: ${traffic.lastSyncedAt}`);
|
|
2097
2135
|
}
|
|
2098
2136
|
}
|
|
2099
2137
|
|
|
@@ -2158,16 +2196,19 @@ var GA_CLI_COMMANDS = [
|
|
|
2158
2196
|
},
|
|
2159
2197
|
{
|
|
2160
2198
|
path: ["ga", "traffic"],
|
|
2161
|
-
usage: "canonry ga traffic <project> [--limit 50] [--format json]",
|
|
2199
|
+
usage: "canonry ga traffic <project> [--limit 50] [--window 30d] [--format json]",
|
|
2162
2200
|
options: {
|
|
2163
|
-
limit: stringOption()
|
|
2201
|
+
limit: stringOption(),
|
|
2202
|
+
window: stringOption()
|
|
2164
2203
|
},
|
|
2165
2204
|
run: async (input) => {
|
|
2166
|
-
const project = requireProject(input, "ga.traffic", "canonry ga traffic <project> [--limit 50] [--format json]");
|
|
2205
|
+
const project = requireProject(input, "ga.traffic", "canonry ga traffic <project> [--limit 50] [--window 30d] [--format json]");
|
|
2167
2206
|
const limitStr = getString(input.values, "limit");
|
|
2168
2207
|
const limit = limitStr ? parseInt(limitStr, 10) : void 0;
|
|
2208
|
+
const window = getString(input.values, "window");
|
|
2169
2209
|
await gaTraffic(project, {
|
|
2170
2210
|
limit,
|
|
2211
|
+
window,
|
|
2171
2212
|
format: input.format
|
|
2172
2213
|
});
|
|
2173
2214
|
}
|
|
@@ -2182,18 +2223,44 @@ var GA_CLI_COMMANDS = [
|
|
|
2182
2223
|
},
|
|
2183
2224
|
{
|
|
2184
2225
|
path: ["ga", "ai-referral-history"],
|
|
2185
|
-
usage: "canonry ga ai-referral-history <project> [--format json]",
|
|
2226
|
+
usage: "canonry ga ai-referral-history <project> [--window 30d] [--format json]",
|
|
2227
|
+
options: {
|
|
2228
|
+
window: stringOption()
|
|
2229
|
+
},
|
|
2186
2230
|
run: async (input) => {
|
|
2187
|
-
const project = requireProject(input, "ga.ai-referral-history", "canonry ga ai-referral-history <project> [--format json]");
|
|
2188
|
-
await gaAiReferralHistory(project,
|
|
2231
|
+
const project = requireProject(input, "ga.ai-referral-history", "canonry ga ai-referral-history <project> [--window 30d] [--format json]");
|
|
2232
|
+
await gaAiReferralHistory(project, {
|
|
2233
|
+
window: getString(input.values, "window"),
|
|
2234
|
+
format: input.format
|
|
2235
|
+
});
|
|
2189
2236
|
}
|
|
2190
2237
|
},
|
|
2191
2238
|
{
|
|
2192
2239
|
path: ["ga", "social-referral-history"],
|
|
2193
|
-
usage: "canonry ga social-referral-history <project> [--format json]",
|
|
2240
|
+
usage: "canonry ga social-referral-history <project> [--window 30d] [--format json]",
|
|
2241
|
+
options: {
|
|
2242
|
+
window: stringOption()
|
|
2243
|
+
},
|
|
2244
|
+
run: async (input) => {
|
|
2245
|
+
const project = requireProject(input, "ga.social-referral-history", "canonry ga social-referral-history <project> [--window 30d] [--format json]");
|
|
2246
|
+
await gaSocialReferralHistory(project, {
|
|
2247
|
+
window: getString(input.values, "window"),
|
|
2248
|
+
format: input.format
|
|
2249
|
+
});
|
|
2250
|
+
}
|
|
2251
|
+
},
|
|
2252
|
+
{
|
|
2253
|
+
path: ["ga", "session-history"],
|
|
2254
|
+
usage: "canonry ga session-history <project> [--window 30d] [--format json]",
|
|
2255
|
+
options: {
|
|
2256
|
+
window: stringOption()
|
|
2257
|
+
},
|
|
2194
2258
|
run: async (input) => {
|
|
2195
|
-
const project = requireProject(input, "ga.
|
|
2196
|
-
await
|
|
2259
|
+
const project = requireProject(input, "ga.session-history", "canonry ga session-history <project> [--window 30d] [--format json]");
|
|
2260
|
+
await gaSessionHistory(project, {
|
|
2261
|
+
window: getString(input.values, "window"),
|
|
2262
|
+
format: input.format
|
|
2263
|
+
});
|
|
2197
2264
|
}
|
|
2198
2265
|
},
|
|
2199
2266
|
{
|
|
@@ -2231,7 +2298,7 @@ var GA_CLI_COMMANDS = [
|
|
|
2231
2298
|
unknownSubcommand(input.positionals[0], {
|
|
2232
2299
|
command: "ga",
|
|
2233
2300
|
usage: "canonry ga <subcommand> <project> [args]",
|
|
2234
|
-
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage", "ai-referral-history", "social-referral-history", "social-referral-summary", "attribution"]
|
|
2301
|
+
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage", "ai-referral-history", "social-referral-history", "session-history", "social-referral-summary", "attribution"]
|
|
2235
2302
|
});
|
|
2236
2303
|
}
|
|
2237
2304
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.46.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -54,20 +54,20 @@
|
|
|
54
54
|
"@types/node-cron": "^3.0.11",
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"tsx": "^4.19.0",
|
|
57
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
58
57
|
"@ainyc/canonry-config": "0.0.0",
|
|
59
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
60
58
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
61
59
|
"@ainyc/canonry-db": "0.0.0",
|
|
62
|
-
"@ainyc/canonry-
|
|
60
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
63
61
|
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
62
|
+
"@ainyc/canonry-integration-google": "0.0.0",
|
|
63
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
64
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
64
65
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
65
|
-
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
66
66
|
"@ainyc/canonry-provider-local": "0.0.0",
|
|
67
|
-
"@ainyc/canonry-
|
|
67
|
+
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
68
69
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-provider-
|
|
70
|
-
"@ainyc/canonry-integration-wordpress": "0.0.0"
|
|
70
|
+
"@ainyc/canonry-provider-openai": "0.0.0"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsup && tsx build-web.ts",
|