@ainyc/canonry 1.40.1 → 1.44.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--ev1Bjls.css +1 -0
- package/assets/assets/index-BAzKj_9S.js +281 -0
- package/assets/index.html +2 -2
- package/dist/{chunk-FOWWBLXD.js → chunk-AATIMNOX.js} +39 -2
- package/dist/{chunk-FXHVGU5S.js → chunk-C3LF36DQ.js} +633 -135
- package/dist/cli.js +287 -11
- package/dist/index.js +2 -2
- package/dist/{intelligence-service-PDZOIB7L.js → intelligence-service-36ERONKI.js} +1 -1
- package/package.json +6 -6
- package/assets/assets/index-DU7KOHur.js +0 -281
- package/assets/assets/index-Djm1st6N.css +0 -1
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-C3LF36DQ.js";
|
|
32
32
|
import {
|
|
33
33
|
apiKeys,
|
|
34
34
|
competitors,
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
projects,
|
|
39
39
|
querySnapshots,
|
|
40
40
|
runs
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-AATIMNOX.js";
|
|
42
42
|
|
|
43
43
|
// src/cli.ts
|
|
44
44
|
import { pathToFileURL } from "url";
|
|
@@ -355,7 +355,7 @@ async function backfillAnswerVisibilityCommand(opts) {
|
|
|
355
355
|
console.log(` Errors: ${providerErrors}`);
|
|
356
356
|
}
|
|
357
357
|
async function backfillInsightsCommand(project, opts) {
|
|
358
|
-
const { IntelligenceService } = await import("./intelligence-service-
|
|
358
|
+
const { IntelligenceService } = await import("./intelligence-service-36ERONKI.js");
|
|
359
359
|
const config = loadConfig();
|
|
360
360
|
const db = createClient(config.database);
|
|
361
361
|
migrate(db);
|
|
@@ -907,6 +907,15 @@ var ApiClient = class {
|
|
|
907
907
|
async gaAiReferralHistory(project) {
|
|
908
908
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/ai-referral-history`);
|
|
909
909
|
}
|
|
910
|
+
async gaSocialReferralHistory(project) {
|
|
911
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-history`);
|
|
912
|
+
}
|
|
913
|
+
async gaSocialReferralTrend(project) {
|
|
914
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/social-referral-trend`);
|
|
915
|
+
}
|
|
916
|
+
async gaAttributionTrend(project) {
|
|
917
|
+
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/attribution-trend`);
|
|
918
|
+
}
|
|
910
919
|
async gaSessionHistory(project) {
|
|
911
920
|
return this.request("GET", `/projects/${encodeURIComponent(project)}/ga/session-history`);
|
|
912
921
|
}
|
|
@@ -1709,14 +1718,21 @@ async function gaStatus(project, format) {
|
|
|
1709
1718
|
}
|
|
1710
1719
|
async function gaSync(project, opts) {
|
|
1711
1720
|
const client = getClient3();
|
|
1712
|
-
const
|
|
1721
|
+
const body = {};
|
|
1722
|
+
if (opts?.days) body.days = opts.days;
|
|
1723
|
+
if (opts?.only) body.only = opts.only;
|
|
1724
|
+
const result = await client.gaSync(project, body);
|
|
1713
1725
|
if (opts?.format === "json") {
|
|
1714
1726
|
console.log(JSON.stringify(result, null, 2));
|
|
1715
1727
|
return;
|
|
1716
1728
|
}
|
|
1717
1729
|
console.log(`GA4 sync complete for "${project}".`);
|
|
1730
|
+
if (result.syncedComponents) {
|
|
1731
|
+
console.log(` Components: ${result.syncedComponents.join(", ")}`);
|
|
1732
|
+
}
|
|
1718
1733
|
console.log(` Page rows: ${result.rowCount}`);
|
|
1719
1734
|
console.log(` AI rows: ${result.aiReferralCount}`);
|
|
1735
|
+
console.log(` Social rows: ${result.socialReferralCount}`);
|
|
1720
1736
|
console.log(` Period: ${result.days} days`);
|
|
1721
1737
|
console.log(` Synced at: ${result.syncedAt}`);
|
|
1722
1738
|
}
|
|
@@ -1729,7 +1745,7 @@ async function gaTraffic(project, opts) {
|
|
|
1729
1745
|
console.log(JSON.stringify(result, null, 2));
|
|
1730
1746
|
return;
|
|
1731
1747
|
}
|
|
1732
|
-
if (result.topPages.length === 0 && result.aiReferrals.length === 0) {
|
|
1748
|
+
if (result.topPages.length === 0 && result.aiReferrals.length === 0 && result.socialReferrals.length === 0) {
|
|
1733
1749
|
console.log('No GA4 traffic data. Run "canonry ga sync <project>" first.');
|
|
1734
1750
|
return;
|
|
1735
1751
|
}
|
|
@@ -1756,6 +1772,23 @@ async function gaTraffic(project, opts) {
|
|
|
1756
1772
|
}
|
|
1757
1773
|
console.log();
|
|
1758
1774
|
}
|
|
1775
|
+
if (result.socialReferrals.length > 0) {
|
|
1776
|
+
const chanWidth = 12;
|
|
1777
|
+
if (result.socialSessions > 0) {
|
|
1778
|
+
const share = result.totalSessions > 0 ? Math.round(result.socialSessions / result.totalSessions * 100) : 0;
|
|
1779
|
+
console.log(` Social Sessions: ${result.socialSessions} (${share}% of total)`);
|
|
1780
|
+
}
|
|
1781
|
+
console.log(" SOCIAL REFERRAL SOURCES");
|
|
1782
|
+
console.log(` ${"SOURCE".padEnd(25)} ${"MEDIUM".padEnd(15)} ${"CHANNEL".padEnd(chanWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1783
|
+
console.log(` ${"\u2500".repeat(25)} ${"\u2500".repeat(15)} ${"\u2500".repeat(chanWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1784
|
+
for (const ref of result.socialReferrals) {
|
|
1785
|
+
const chanLabel = ref.channelGroup === "Paid Social" ? "paid" : "organic";
|
|
1786
|
+
console.log(
|
|
1787
|
+
` ${ref.source.padEnd(25)} ${ref.medium.padEnd(15)} ${chanLabel.padEnd(chanWidth)} ${String(ref.sessions).padEnd(10)}${String(ref.users).padEnd(8)}`
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1790
|
+
console.log();
|
|
1791
|
+
}
|
|
1759
1792
|
if (result.topPages.length > 0) {
|
|
1760
1793
|
const pageWidth = Math.min(60, Math.max(15, ...result.topPages.map((r) => r.landingPage.length)));
|
|
1761
1794
|
console.log(` TOP LANDING PAGES`);
|
|
@@ -1798,6 +1831,31 @@ async function gaAiReferralHistory(project, format) {
|
|
|
1798
1831
|
);
|
|
1799
1832
|
}
|
|
1800
1833
|
}
|
|
1834
|
+
async function gaSocialReferralHistory(project, format) {
|
|
1835
|
+
const client = getClient3();
|
|
1836
|
+
const result = await client.gaSocialReferralHistory(project);
|
|
1837
|
+
if (format === "json") {
|
|
1838
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
if (result.length === 0) {
|
|
1842
|
+
console.log('No social referral history. Run "canonry ga sync <project>" first.');
|
|
1843
|
+
return;
|
|
1844
|
+
}
|
|
1845
|
+
const dateWidth = 12;
|
|
1846
|
+
const sourceWidth = Math.min(30, Math.max(10, ...result.map((r) => r.source.length)));
|
|
1847
|
+
const chanWidth = 12;
|
|
1848
|
+
console.log(`GA4 Social Referral History for "${project}":
|
|
1849
|
+
`);
|
|
1850
|
+
console.log(` ${"DATE".padEnd(dateWidth)} ${"SOURCE".padEnd(sourceWidth)} ${"CHANNEL".padEnd(chanWidth)} ${"SESSIONS".padEnd(10)}${"USERS".padEnd(8)}`);
|
|
1851
|
+
console.log(` ${"\u2500".repeat(dateWidth)} ${"\u2500".repeat(sourceWidth)} ${"\u2500".repeat(chanWidth)} ${"\u2500".repeat(10)}${"\u2500".repeat(8)}`);
|
|
1852
|
+
for (const row of result) {
|
|
1853
|
+
const chanLabel = row.channelGroup === "Paid Social" ? "paid" : "organic";
|
|
1854
|
+
console.log(
|
|
1855
|
+
` ${row.date.padEnd(dateWidth)} ${row.source.padEnd(sourceWidth)} ${chanLabel.padEnd(chanWidth)} ${String(row.sessions).padEnd(10)}${String(row.users).padEnd(8)}`
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1801
1859
|
async function gaCoverage(project, format) {
|
|
1802
1860
|
const client = getClient3();
|
|
1803
1861
|
const result = await client.gaCoverage(project);
|
|
@@ -1821,6 +1879,182 @@ async function gaCoverage(project, format) {
|
|
|
1821
1879
|
);
|
|
1822
1880
|
}
|
|
1823
1881
|
}
|
|
1882
|
+
async function gaSocialReferralSummary(project, opts) {
|
|
1883
|
+
const client = getClient3();
|
|
1884
|
+
const traffic = await client.gaTraffic(project);
|
|
1885
|
+
if (opts?.trend) {
|
|
1886
|
+
const trend = await client.gaSocialReferralTrend(project);
|
|
1887
|
+
if (opts.format === "json") {
|
|
1888
|
+
console.log(JSON.stringify({
|
|
1889
|
+
socialSessions: traffic.socialSessions,
|
|
1890
|
+
socialUsers: traffic.socialUsers,
|
|
1891
|
+
totalSessions: traffic.totalSessions,
|
|
1892
|
+
socialSharePct: traffic.socialSharePct,
|
|
1893
|
+
topSources: traffic.socialReferrals.slice(0, 5).map((r) => ({ source: r.source, sessions: r.sessions, channel: r.channelGroup })),
|
|
1894
|
+
trend
|
|
1895
|
+
}, null, 2));
|
|
1896
|
+
return;
|
|
1897
|
+
}
|
|
1898
|
+
console.log(`Social Traffic Summary for "${project}"
|
|
1899
|
+
`);
|
|
1900
|
+
console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
|
|
1901
|
+
console.log(` Users: ${traffic.socialUsers}`);
|
|
1902
|
+
console.log();
|
|
1903
|
+
const fmtTrend = (pct) => pct === null ? "n/a" : `${pct >= 0 ? "+" : ""}${pct}%`;
|
|
1904
|
+
console.log(` 7d trend: ${fmtTrend(trend.trend7dPct)} (${trend.socialSessions7d} vs ${trend.socialSessionsPrev7d})`);
|
|
1905
|
+
console.log(` 30d trend: ${fmtTrend(trend.trend30dPct)} (${trend.socialSessions30d} vs ${trend.socialSessionsPrev30d})`);
|
|
1906
|
+
if (trend.biggestMover) {
|
|
1907
|
+
const m = trend.biggestMover;
|
|
1908
|
+
console.log(` Mover: ${m.source} (${m.changePct >= 0 ? "+" : ""}${m.changePct}%, ${m.sessionsPrev7d}\u2192${m.sessions7d})`);
|
|
1909
|
+
}
|
|
1910
|
+
console.log();
|
|
1911
|
+
if (traffic.socialReferrals.length > 0) {
|
|
1912
|
+
console.log(" TOP SOURCES");
|
|
1913
|
+
for (const ref of traffic.socialReferrals.slice(0, 5)) {
|
|
1914
|
+
const chanLabel = ref.channelGroup === "Paid Social" ? "paid" : "organic";
|
|
1915
|
+
console.log(` ${ref.source.padEnd(20)} ${String(ref.sessions).padEnd(8)} sessions (${chanLabel})`);
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
if (opts?.format === "json") {
|
|
1921
|
+
console.log(JSON.stringify({
|
|
1922
|
+
socialSessions: traffic.socialSessions,
|
|
1923
|
+
socialUsers: traffic.socialUsers,
|
|
1924
|
+
totalSessions: traffic.totalSessions,
|
|
1925
|
+
socialSharePct: traffic.socialSharePct,
|
|
1926
|
+
topSources: traffic.socialReferrals.slice(0, 5).map((r) => ({ source: r.source, sessions: r.sessions, channel: r.channelGroup }))
|
|
1927
|
+
}, null, 2));
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
console.log(`Social Traffic Summary for "${project}"
|
|
1931
|
+
`);
|
|
1932
|
+
console.log(` Sessions: ${traffic.socialSessions} (${traffic.socialSharePct}% of ${traffic.totalSessions} total)`);
|
|
1933
|
+
console.log(` Users: ${traffic.socialUsers}`);
|
|
1934
|
+
if (traffic.socialReferrals.length > 0) {
|
|
1935
|
+
console.log();
|
|
1936
|
+
console.log(" TOP SOURCES");
|
|
1937
|
+
for (const ref of traffic.socialReferrals.slice(0, 5)) {
|
|
1938
|
+
const chanLabel = ref.channelGroup === "Paid Social" ? "paid" : "organic";
|
|
1939
|
+
console.log(` ${ref.source.padEnd(20)} ${String(ref.sessions).padEnd(8)} sessions (${chanLabel})`);
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
async function gaAttribution(project, opts) {
|
|
1944
|
+
const client = getClient3();
|
|
1945
|
+
const traffic = await client.gaTraffic(project);
|
|
1946
|
+
const fmtTrend = (pct) => pct === null ? "n/a" : `${pct >= 0 ? "+" : ""}${pct}%`;
|
|
1947
|
+
if (opts?.trend) {
|
|
1948
|
+
const trend = await client.gaAttributionTrend(project);
|
|
1949
|
+
if (opts.format === "json") {
|
|
1950
|
+
console.log(JSON.stringify({
|
|
1951
|
+
totalSessions: traffic.totalSessions,
|
|
1952
|
+
totalUsers: traffic.totalUsers,
|
|
1953
|
+
organicSessions: traffic.totalOrganicSessions,
|
|
1954
|
+
aiSessions: traffic.aiSessionsDeduped,
|
|
1955
|
+
aiUsers: traffic.aiUsersDeduped,
|
|
1956
|
+
socialSessions: traffic.socialSessions,
|
|
1957
|
+
socialUsers: traffic.socialUsers,
|
|
1958
|
+
aiSharePct: traffic.aiSharePct,
|
|
1959
|
+
socialSharePct: traffic.socialSharePct,
|
|
1960
|
+
organicSharePct: traffic.organicSharePct,
|
|
1961
|
+
aiReferrals: traffic.aiReferrals,
|
|
1962
|
+
socialReferrals: traffic.socialReferrals,
|
|
1963
|
+
trend
|
|
1964
|
+
}, null, 2));
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
if (traffic.totalSessions === 0) {
|
|
1968
|
+
console.log('No GA4 traffic data. Run "canonry ga sync <project>" first.');
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
console.log(`GA4 Attribution Overview for "${project}"
|
|
1972
|
+
`);
|
|
1973
|
+
console.log(` Total Sessions: ${traffic.totalSessions}`);
|
|
1974
|
+
console.log(` Total Users: ${traffic.totalUsers}`);
|
|
1975
|
+
console.log();
|
|
1976
|
+
console.log(" CHANNEL BREAKDOWN 7d trend 30d trend");
|
|
1977
|
+
console.log(` Organic Search: ${String(traffic.totalOrganicSessions).padEnd(6)} (${String(traffic.organicSharePct).padStart(2)}%) ${fmtTrend(trend.organic.trend7dPct).padEnd(12)} ${fmtTrend(trend.organic.trend30dPct)}`);
|
|
1978
|
+
console.log(` AI Referrals: ${String(traffic.aiSessionsDeduped).padEnd(6)} (${String(traffic.aiSharePct).padStart(2)}%) ${fmtTrend(trend.ai.trend7dPct).padEnd(12)} ${fmtTrend(trend.ai.trend30dPct)}`);
|
|
1979
|
+
console.log(` Social: ${String(traffic.socialSessions).padEnd(6)} (${String(traffic.socialSharePct).padStart(2)}%) ${fmtTrend(trend.social.trend7dPct).padEnd(12)} ${fmtTrend(trend.social.trend30dPct)}`);
|
|
1980
|
+
const otherSessions2 = traffic.totalSessions - traffic.totalOrganicSessions - traffic.aiSessionsDeduped - traffic.socialSessions;
|
|
1981
|
+
if (otherSessions2 > 0) {
|
|
1982
|
+
const otherPct = traffic.totalSessions > 0 ? Math.round(otherSessions2 / traffic.totalSessions * 100) : 0;
|
|
1983
|
+
console.log(` Other: ${String(otherSessions2).padEnd(6)} (${String(otherPct).padStart(2)}%)`);
|
|
1984
|
+
}
|
|
1985
|
+
console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
1986
|
+
console.log(` Total: ${String(traffic.totalSessions).padEnd(6)} ${fmtTrend(trend.total.trend7dPct).padEnd(12)} ${fmtTrend(trend.total.trend30dPct)}`);
|
|
1987
|
+
if (trend.aiBiggestMover) {
|
|
1988
|
+
const m = trend.aiBiggestMover;
|
|
1989
|
+
console.log(`
|
|
1990
|
+
AI Mover: ${m.source} (${m.changePct >= 0 ? "+" : ""}${m.changePct}%, ${m.sessionsPrev7d}\u2192${m.sessions7d} sessions/7d)`);
|
|
1991
|
+
}
|
|
1992
|
+
if (trend.socialBiggestMover) {
|
|
1993
|
+
const m = trend.socialBiggestMover;
|
|
1994
|
+
console.log(` Social Mover: ${m.source} (${m.changePct >= 0 ? "+" : ""}${m.changePct}%, ${m.sessionsPrev7d}\u2192${m.sessions7d} sessions/7d)`);
|
|
1995
|
+
}
|
|
1996
|
+
if (traffic.lastSyncedAt) {
|
|
1997
|
+
console.log(`
|
|
1998
|
+
Last synced: ${traffic.lastSyncedAt}`);
|
|
1999
|
+
}
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
if (opts?.format === "json") {
|
|
2003
|
+
console.log(JSON.stringify({
|
|
2004
|
+
totalSessions: traffic.totalSessions,
|
|
2005
|
+
totalUsers: traffic.totalUsers,
|
|
2006
|
+
organicSessions: traffic.totalOrganicSessions,
|
|
2007
|
+
aiSessions: traffic.aiSessionsDeduped,
|
|
2008
|
+
aiUsers: traffic.aiUsersDeduped,
|
|
2009
|
+
socialSessions: traffic.socialSessions,
|
|
2010
|
+
socialUsers: traffic.socialUsers,
|
|
2011
|
+
aiSharePct: traffic.aiSharePct,
|
|
2012
|
+
socialSharePct: traffic.socialSharePct,
|
|
2013
|
+
organicSharePct: traffic.organicSharePct,
|
|
2014
|
+
aiReferrals: traffic.aiReferrals,
|
|
2015
|
+
socialReferrals: traffic.socialReferrals
|
|
2016
|
+
}, null, 2));
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
if (traffic.totalSessions === 0) {
|
|
2020
|
+
console.log('No GA4 traffic data. Run "canonry ga sync <project>" first.');
|
|
2021
|
+
return;
|
|
2022
|
+
}
|
|
2023
|
+
console.log(`GA4 Attribution Overview for "${project}"
|
|
2024
|
+
`);
|
|
2025
|
+
console.log(` Total Sessions: ${traffic.totalSessions}`);
|
|
2026
|
+
console.log(` Total Users: ${traffic.totalUsers}`);
|
|
2027
|
+
console.log();
|
|
2028
|
+
console.log(" CHANNEL BREAKDOWN");
|
|
2029
|
+
console.log(` Organic Search: ${traffic.totalOrganicSessions} sessions (${traffic.organicSharePct}%)`);
|
|
2030
|
+
console.log(` AI Referrals: ${traffic.aiSessionsDeduped} sessions (${traffic.aiSharePct}%)`);
|
|
2031
|
+
console.log(` Social: ${traffic.socialSessions} sessions (${traffic.socialSharePct}%)`);
|
|
2032
|
+
const otherSessions = traffic.totalSessions - traffic.totalOrganicSessions - traffic.aiSessionsDeduped - traffic.socialSessions;
|
|
2033
|
+
if (otherSessions > 0) {
|
|
2034
|
+
const otherPct = traffic.totalSessions > 0 ? Math.round(otherSessions / traffic.totalSessions * 100) : 0;
|
|
2035
|
+
console.log(` Other: ${otherSessions} sessions (${otherPct}%)`);
|
|
2036
|
+
}
|
|
2037
|
+
if (traffic.aiReferrals.length > 0) {
|
|
2038
|
+
console.log();
|
|
2039
|
+
console.log(" AI SOURCES");
|
|
2040
|
+
for (const ref of traffic.aiReferrals.slice(0, 10)) {
|
|
2041
|
+
const dimLabel = ref.sourceDimension === "first_user" ? "first-visit" : ref.sourceDimension === "manual_utm" ? "utm" : "session";
|
|
2042
|
+
console.log(` ${ref.source.padEnd(25)} ${String(ref.sessions).padEnd(8)} sessions (${dimLabel})`);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
if (traffic.socialReferrals.length > 0) {
|
|
2046
|
+
console.log();
|
|
2047
|
+
console.log(" SOCIAL SOURCES");
|
|
2048
|
+
for (const ref of traffic.socialReferrals.slice(0, 10)) {
|
|
2049
|
+
const chanLabel = ref.channelGroup === "Paid Social" ? "paid" : "organic";
|
|
2050
|
+
console.log(` ${ref.source.padEnd(25)} ${String(ref.sessions).padEnd(8)} sessions (${chanLabel})`);
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
if (traffic.lastSyncedAt) {
|
|
2054
|
+
console.log(`
|
|
2055
|
+
Last synced: ${traffic.lastSyncedAt}`);
|
|
2056
|
+
}
|
|
2057
|
+
}
|
|
1824
2058
|
|
|
1825
2059
|
// src/cli-commands/ga.ts
|
|
1826
2060
|
var GA_CLI_COMMANDS = [
|
|
@@ -1864,16 +2098,19 @@ var GA_CLI_COMMANDS = [
|
|
|
1864
2098
|
},
|
|
1865
2099
|
{
|
|
1866
2100
|
path: ["ga", "sync"],
|
|
1867
|
-
usage: "canonry ga sync <project> [--days 30] [--format json]",
|
|
2101
|
+
usage: "canonry ga sync <project> [--days 30] [--only traffic|ai|social] [--format json]",
|
|
1868
2102
|
options: {
|
|
1869
|
-
days: stringOption()
|
|
2103
|
+
days: stringOption(),
|
|
2104
|
+
only: stringOption()
|
|
1870
2105
|
},
|
|
1871
2106
|
run: async (input) => {
|
|
1872
|
-
const project = requireProject(input, "ga.sync", "canonry ga sync <project> [--days 30] [--format json]");
|
|
2107
|
+
const project = requireProject(input, "ga.sync", "canonry ga sync <project> [--days 30] [--only traffic|ai|social] [--format json]");
|
|
1873
2108
|
const daysStr = getString(input.values, "days");
|
|
1874
2109
|
const days = daysStr ? parseInt(daysStr, 10) : void 0;
|
|
2110
|
+
const only = getString(input.values, "only");
|
|
1875
2111
|
await gaSync(project, {
|
|
1876
2112
|
days,
|
|
2113
|
+
only,
|
|
1877
2114
|
format: input.format
|
|
1878
2115
|
});
|
|
1879
2116
|
}
|
|
@@ -1910,14 +2147,50 @@ var GA_CLI_COMMANDS = [
|
|
|
1910
2147
|
await gaAiReferralHistory(project, input.format);
|
|
1911
2148
|
}
|
|
1912
2149
|
},
|
|
2150
|
+
{
|
|
2151
|
+
path: ["ga", "social-referral-history"],
|
|
2152
|
+
usage: "canonry ga social-referral-history <project> [--format json]",
|
|
2153
|
+
run: async (input) => {
|
|
2154
|
+
const project = requireProject(input, "ga.social-referral-history", "canonry ga social-referral-history <project> [--format json]");
|
|
2155
|
+
await gaSocialReferralHistory(project, input.format);
|
|
2156
|
+
}
|
|
2157
|
+
},
|
|
2158
|
+
{
|
|
2159
|
+
path: ["ga", "social-referral-summary"],
|
|
2160
|
+
usage: "canonry ga social-referral-summary <project> [--trend] [--format json]",
|
|
2161
|
+
options: {
|
|
2162
|
+
trend: { type: "boolean", default: false }
|
|
2163
|
+
},
|
|
2164
|
+
run: async (input) => {
|
|
2165
|
+
const project = requireProject(input, "ga.social-referral-summary", "canonry ga social-referral-summary <project> [--trend] [--format json]");
|
|
2166
|
+
await gaSocialReferralSummary(project, {
|
|
2167
|
+
trend: input.values.trend === true,
|
|
2168
|
+
format: input.format
|
|
2169
|
+
});
|
|
2170
|
+
}
|
|
2171
|
+
},
|
|
2172
|
+
{
|
|
2173
|
+
path: ["ga", "attribution"],
|
|
2174
|
+
usage: "canonry ga attribution <project> [--trend] [--format json]",
|
|
2175
|
+
options: {
|
|
2176
|
+
trend: { type: "boolean", default: false }
|
|
2177
|
+
},
|
|
2178
|
+
run: async (input) => {
|
|
2179
|
+
const project = requireProject(input, "ga.attribution", "canonry ga attribution <project> [--trend] [--format json]");
|
|
2180
|
+
await gaAttribution(project, {
|
|
2181
|
+
trend: input.values.trend === true,
|
|
2182
|
+
format: input.format
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
},
|
|
1913
2186
|
{
|
|
1914
2187
|
path: ["ga"],
|
|
1915
|
-
usage: "canonry ga <
|
|
2188
|
+
usage: "canonry ga <subcommand> <project> [args]",
|
|
1916
2189
|
run: async (input) => {
|
|
1917
2190
|
unknownSubcommand(input.positionals[0], {
|
|
1918
2191
|
command: "ga",
|
|
1919
|
-
usage: "canonry ga <
|
|
1920
|
-
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage", "ai-referral-history"]
|
|
2192
|
+
usage: "canonry ga <subcommand> <project> [args]",
|
|
2193
|
+
available: ["connect", "disconnect", "status", "sync", "traffic", "coverage", "ai-referral-history", "social-referral-history", "social-referral-summary", "attribution"]
|
|
1921
2194
|
});
|
|
1922
2195
|
}
|
|
1923
2196
|
}
|
|
@@ -5937,7 +6210,10 @@ async function serveCommand(format = "text") {
|
|
|
5937
6210
|
const db = createClient(config.database);
|
|
5938
6211
|
migrate(db);
|
|
5939
6212
|
const app = await createServer({ config, db });
|
|
6213
|
+
let shuttingDown = false;
|
|
5940
6214
|
const shutdown = () => {
|
|
6215
|
+
if (shuttingDown) return;
|
|
6216
|
+
shuttingDown = true;
|
|
5941
6217
|
app.close().then(() => {
|
|
5942
6218
|
process.exit(0);
|
|
5943
6219
|
}).catch(() => {
|
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.44.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-api-routes": "0.0.0",
|
|
58
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
59
57
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
58
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
60
59
|
"@ainyc/canonry-db": "0.0.0",
|
|
61
60
|
"@ainyc/canonry-intelligence": "0.0.0",
|
|
61
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
62
62
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
63
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
63
64
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
64
65
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
65
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
66
66
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
67
67
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
68
|
-
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
69
68
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
70
|
-
"@ainyc/canonry-provider-local": "0.0.0"
|
|
69
|
+
"@ainyc/canonry-provider-local": "0.0.0",
|
|
70
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0"
|
|
71
71
|
},
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build": "tsup && tsx build-web.ts",
|