@orion-studios/payload-seo-audit 1.0.0 → 1.1.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/README.md +48 -45
- package/dist/api/cron.d.ts.map +1 -1
- package/dist/api/cron.js +3 -23
- package/dist/api/run-stream.d.ts.map +1 -1
- package/dist/api/run-stream.js +19 -215
- package/dist/api/run.d.ts.map +1 -1
- package/dist/api/run.js +4 -25
- package/dist/collections/SeoSnapshots.d.ts.map +1 -1
- package/dist/collections/SeoSnapshots.js +26 -0
- package/dist/components/types.d.ts +10 -0
- package/dist/components/types.d.ts.map +1 -1
- package/dist/components/views/SeoDashboard.js +29 -17
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/globals/SeoIntegrations.d.ts +3 -0
- package/dist/globals/SeoIntegrations.d.ts.map +1 -0
- package/dist/globals/SeoIntegrations.js +305 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/utilities/crux.d.ts +6 -0
- package/dist/utilities/crux.d.ts.map +1 -0
- package/dist/utilities/crux.js +244 -0
- package/dist/utilities/dataforseo.d.ts +12 -0
- package/dist/utilities/dataforseo.d.ts.map +1 -0
- package/dist/utilities/dataforseo.js +169 -0
- package/dist/utilities/gsc.d.ts +4 -11
- package/dist/utilities/gsc.d.ts.map +1 -1
- package/dist/utilities/gsc.js +58 -22
- package/dist/utilities/integrationSettings.d.ts +10 -0
- package/dist/utilities/integrationSettings.d.ts.map +1 -0
- package/dist/utilities/integrationSettings.js +198 -0
- package/dist/utilities/opsWebhook.d.ts +15 -0
- package/dist/utilities/opsWebhook.d.ts.map +1 -0
- package/dist/utilities/opsWebhook.js +130 -0
- package/dist/utilities/pagespeed.d.ts +1 -1
- package/dist/utilities/pagespeed.d.ts.map +1 -1
- package/dist/utilities/pagespeed.js +11 -5
- package/dist/utilities/providers.d.ts +2 -2
- package/dist/utilities/providers.d.ts.map +1 -1
- package/dist/utilities/providers.js +12 -7
- package/dist/utilities/runAudit.d.ts +4 -1
- package/dist/utilities/runAudit.d.ts.map +1 -1
- package/dist/utilities/runAudit.js +112 -11
- package/dist/utilities/secrets.d.ts +23 -0
- package/dist/utilities/secrets.d.ts.map +1 -0
- package/dist/utilities/secrets.js +108 -0
- package/dist/utilities/types.d.ts +85 -0
- package/dist/utilities/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,14 +5,15 @@ Professional SEO audit system for Payload CMS 3.0 + Next.js 15 projects.
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- 🔍 **Comprehensive SEO Analysis** - Crawls your site and checks 50+ SEO factors
|
|
8
|
-
- 📊 **Visual Dashboard** -
|
|
8
|
+
- 📊 **Visual Dashboard** - Admin UI with scores, trends, issues, and CrUX metrics
|
|
9
9
|
- 🎯 **Category Scoring** - Metadata, indexability, structure, links, media, structured data, performance
|
|
10
|
-
- 📈 **Trend Tracking** - Monitor
|
|
11
|
-
- ⚡ **Performance
|
|
10
|
+
- 📈 **Trend Tracking** - Monitor SEO performance over time
|
|
11
|
+
- ⚡ **Performance Integrations** - Google PageSpeed + Chrome UX Report (CrUX)
|
|
12
|
+
- 🔎 **Search Visibility Sync** - Google Search Console keyword visibility imports
|
|
13
|
+
- 🔗 **Authority Snapshots** - DataForSEO authority/backlink snapshots with run policy controls
|
|
12
14
|
- 🔄 **Auto-Trigger** - Optionally run audits when content is published
|
|
13
|
-
-
|
|
14
|
-
- 📄 **PDF Export** - Download
|
|
15
|
-
- 🔌 **Easy Integration** - Simple plugin system with automated setup
|
|
15
|
+
- 🔐 **Encrypted Integration Settings** - Credentials managed in Payload admin (with env fallback)
|
|
16
|
+
- 📄 **PDF Export** - Download snapshot reports
|
|
16
17
|
|
|
17
18
|
## Quick Start
|
|
18
19
|
|
|
@@ -28,7 +29,7 @@ npm install @orion-studios/payload-seo-audit
|
|
|
28
29
|
# 1. Run the automated setup tool
|
|
29
30
|
npx payload-seo-audit init
|
|
30
31
|
|
|
31
|
-
# 2. Configure
|
|
32
|
+
# 2. Configure required environment variables (.env.local)
|
|
32
33
|
SEO_AUDIT_SECRET=<random-secret-key>
|
|
33
34
|
NEXT_PUBLIC_SERVER_URL=https://your-site.com
|
|
34
35
|
|
|
@@ -54,10 +55,7 @@ export default buildConfig({
|
|
|
54
55
|
domain: 'www.yoursite.com',
|
|
55
56
|
canonicalHost: 'https://www.yoursite.com',
|
|
56
57
|
sitemapURL: 'https://www.yoursite.com/sitemap.xml',
|
|
57
|
-
keyURLs: [
|
|
58
|
-
'https://www.yoursite.com',
|
|
59
|
-
'https://www.yoursite.com/about',
|
|
60
|
-
],
|
|
58
|
+
keyURLs: ['https://www.yoursite.com', 'https://www.yoursite.com/about'],
|
|
61
59
|
},
|
|
62
60
|
crawl: {
|
|
63
61
|
maxPages: 120,
|
|
@@ -69,54 +67,59 @@ export default buildConfig({
|
|
|
69
67
|
globals: ['home'],
|
|
70
68
|
},
|
|
71
69
|
access: (user) => user?.role === 'admin',
|
|
70
|
+
integrations: {
|
|
71
|
+
enablePageSpeed: true,
|
|
72
|
+
enableSearchConsole: false,
|
|
73
|
+
enableCrUX: false,
|
|
74
|
+
},
|
|
72
75
|
}),
|
|
73
76
|
],
|
|
74
77
|
})
|
|
75
78
|
```
|
|
76
79
|
|
|
77
|
-
###
|
|
78
|
-
|
|
79
|
-
1. Visit `/admin/globals/seo-dashboard`
|
|
80
|
-
2. Click **"Run Audit Now"**
|
|
81
|
-
3. View comprehensive SEO analysis
|
|
82
|
-
4. Click on snapshots to see detailed reports
|
|
83
|
-
5. Track your improvements over time
|
|
84
|
-
|
|
85
|
-
## Documentation
|
|
80
|
+
### Configure API Integrations in Admin
|
|
86
81
|
|
|
87
|
-
|
|
88
|
-
- **[Configuration Options](./INTEGRATION.md#step-2-configure-payload-plugin)** - All plugin config options
|
|
89
|
-
- **[Troubleshooting](./INTEGRATION.md#troubleshooting)** - Common issues and solutions
|
|
82
|
+
After startup, open:
|
|
90
83
|
|
|
91
|
-
|
|
84
|
+
- `/admin/globals/seo-integrations`
|
|
92
85
|
|
|
93
|
-
|
|
86
|
+
From there you can securely configure:
|
|
94
87
|
|
|
95
|
-
|
|
88
|
+
- Google Search Console (OAuth or service account)
|
|
89
|
+
- PageSpeed API key
|
|
90
|
+
- CrUX API key and query scope
|
|
91
|
+
- DataForSEO credentials + run policy
|
|
92
|
+
- Private operator webhook settings
|
|
96
93
|
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
content: [
|
|
100
|
-
'./src/**/*.{js,ts,jsx,tsx}',
|
|
101
|
-
'./node_modules/@orion-studios/payload-seo-audit/dist/**/*.js',
|
|
102
|
-
]
|
|
103
|
-
```
|
|
94
|
+
Secrets are encrypted at rest and masked in the admin form.
|
|
104
95
|
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
darkMode: ['selector', '[data-theme="dark"]'],
|
|
108
|
-
```
|
|
96
|
+
### Usage
|
|
109
97
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
98
|
+
1. Visit `/admin/globals/seo-dashboard`
|
|
99
|
+
2. Click **Run Audit Now**
|
|
100
|
+
3. Review scores, issues, trends, and CrUX field data
|
|
101
|
+
4. Open snapshots for detailed reports and exports
|
|
102
|
+
|
|
103
|
+
## Environment Variable Fallbacks
|
|
104
|
+
|
|
105
|
+
If `seo-integrations` is not configured yet, these env vars are used as fallback:
|
|
106
|
+
|
|
107
|
+
- `SEO_GSC_CLIENT_ID`
|
|
108
|
+
- `SEO_GSC_CLIENT_SECRET`
|
|
109
|
+
- `SEO_GSC_REDIRECT_URI`
|
|
110
|
+
- `SEO_GSC_REFRESH_TOKEN`
|
|
111
|
+
- `GOOGLE_SERVICE_ACCOUNT_EMAIL`
|
|
112
|
+
- `GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY`
|
|
113
|
+
- `SEO_PAGESPEED_API_KEY`
|
|
114
|
+
- `SEO_CRUX_API_KEY`
|
|
115
|
+
- `SEO_DATAFORSEO_LOGIN`
|
|
116
|
+
- `SEO_DATAFORSEO_PASSWORD`
|
|
117
|
+
- `SEO_DATAFORSEO_BASE_URL`
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
document.documentElement.classList.add('dark')
|
|
117
|
-
```
|
|
119
|
+
## Documentation
|
|
118
120
|
|
|
119
|
-
|
|
121
|
+
- **[Integration Guide](./INTEGRATION.md)** - Full setup and troubleshooting
|
|
122
|
+
- **[Troubleshooting](./INTEGRATION.md#troubleshooting)** - Common issues and fixes
|
|
120
123
|
|
|
121
124
|
## License
|
|
122
125
|
|
package/dist/api/cron.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/api/cron.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/api/cron.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM5D,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAmCjG"}
|
package/dist/api/cron.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.handleSeoCron = handleSeoCron;
|
|
37
37
|
const auth_1 = require("../utilities/auth");
|
|
38
38
|
const index_1 = require("../index");
|
|
39
|
+
const integrationSettings_1 = require("../utilities/integrationSettings");
|
|
39
40
|
const runAudit_1 = require("../utilities/runAudit");
|
|
40
41
|
async function handleSeoCron(payload, request) {
|
|
41
42
|
const { NextResponse } = await Promise.resolve().then(() => __importStar(require('next/server')));
|
|
@@ -47,32 +48,11 @@ async function handleSeoCron(payload, request) {
|
|
|
47
48
|
if (!seoConfig) {
|
|
48
49
|
return NextResponse.json({ error: 'SEO Audit plugin not configured' }, { status: 500 });
|
|
49
50
|
}
|
|
50
|
-
const site =
|
|
51
|
-
id: 1,
|
|
52
|
-
name: seoConfig.site.name,
|
|
53
|
-
domain: seoConfig.site.domain,
|
|
54
|
-
canonicalHost: seoConfig.site.canonicalHost,
|
|
55
|
-
sitemapURL: seoConfig.site.sitemapURL,
|
|
56
|
-
keyURLs: seoConfig.site.keyURLs.map((url) => ({ url })),
|
|
57
|
-
crawlSettings: {
|
|
58
|
-
maxPages: seoConfig.crawl.maxPages,
|
|
59
|
-
maxDepth: seoConfig.crawl.maxDepth,
|
|
60
|
-
requestTimeoutMs: seoConfig.crawl.requestTimeoutMs,
|
|
61
|
-
includePatterns: seoConfig.crawl.includePatterns.map((pattern) => ({ pattern })),
|
|
62
|
-
excludePatterns: seoConfig.crawl.excludePatterns.map((pattern) => ({ pattern })),
|
|
63
|
-
},
|
|
64
|
-
integrations: {
|
|
65
|
-
enablePageSpeed: seoConfig.integrations.enablePageSpeed,
|
|
66
|
-
enableSearchConsole: seoConfig.integrations.enableSearchConsole,
|
|
67
|
-
},
|
|
68
|
-
thresholds: {
|
|
69
|
-
targetLCPMs: seoConfig.thresholds.targetLCPMs,
|
|
70
|
-
targetCLS: seoConfig.thresholds.targetCLS,
|
|
71
|
-
},
|
|
72
|
-
};
|
|
51
|
+
const site = (0, integrationSettings_1.siteFromSeoConfig)(seoConfig);
|
|
73
52
|
const result = await (0, runAudit_1.runSEOSnapshot)({
|
|
74
53
|
payload,
|
|
75
54
|
site,
|
|
55
|
+
seoConfig,
|
|
76
56
|
runType: 'scheduled',
|
|
77
57
|
});
|
|
78
58
|
return NextResponse.json({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../src/api/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"run-stream.d.ts","sourceRoot":"","sources":["../../src/api/run-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAY9C,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4ElG"}
|
package/dist/api/run-stream.js
CHANGED
|
@@ -3,61 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.handleSeoRunStream = handleSeoRunStream;
|
|
4
4
|
const auth_1 = require("../utilities/auth");
|
|
5
5
|
const index_1 = require("../index");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const helpers_1 = require("../utilities/helpers");
|
|
9
|
-
const gsc_1 = require("../utilities/gsc");
|
|
10
|
-
const pagespeed_1 = require("../utilities/pagespeed");
|
|
11
|
-
const scoring_1 = require("../utilities/scoring");
|
|
12
|
-
const providers_1 = require("../utilities/providers");
|
|
6
|
+
const integrationSettings_1 = require("../utilities/integrationSettings");
|
|
7
|
+
const runAudit_1 = require("../utilities/runAudit");
|
|
13
8
|
const resolveRunType = (value) => {
|
|
14
9
|
if (value === 'scheduled' || value === 'publish-triggered')
|
|
15
10
|
return value;
|
|
16
11
|
return 'manual';
|
|
17
12
|
};
|
|
18
|
-
const average = (values) => {
|
|
19
|
-
if (!values.length)
|
|
20
|
-
return 0;
|
|
21
|
-
return Math.round(values.reduce((sum, value) => sum + value, 0) / values.length);
|
|
22
|
-
};
|
|
23
|
-
const applyPerformanceIssues = (issues, pageSpeed, site) => {
|
|
24
|
-
if (!pageSpeed)
|
|
25
|
-
return issues;
|
|
26
|
-
const nextIssues = [...issues];
|
|
27
|
-
if (typeof pageSpeed.averagePerformanceScore === 'number' && pageSpeed.averagePerformanceScore < 70) {
|
|
28
|
-
nextIssues.push({
|
|
29
|
-
fingerprint: `perf-score-${pageSpeed.averagePerformanceScore}`,
|
|
30
|
-
ruleID: 'pagespeed-performance-low',
|
|
31
|
-
category: 'performance',
|
|
32
|
-
severity: pageSpeed.averagePerformanceScore < 50 ? 'high' : 'medium',
|
|
33
|
-
message: `Average Lighthouse performance score is ${pageSpeed.averagePerformanceScore}.`,
|
|
34
|
-
recommendation: 'Optimize render-blocking assets, image delivery, and JS execution.',
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
const targetLCP = Number(site.thresholds?.targetLCPMs || 2500);
|
|
38
|
-
if (typeof pageSpeed.averageLCPMs === 'number' && pageSpeed.averageLCPMs > targetLCP) {
|
|
39
|
-
nextIssues.push({
|
|
40
|
-
fingerprint: `perf-lcp-${pageSpeed.averageLCPMs}`,
|
|
41
|
-
ruleID: 'pagespeed-lcp-high',
|
|
42
|
-
category: 'performance',
|
|
43
|
-
severity: pageSpeed.averageLCPMs > targetLCP * 1.5 ? 'high' : 'medium',
|
|
44
|
-
message: `Average LCP is ${pageSpeed.averageLCPMs}ms.`,
|
|
45
|
-
recommendation: 'Improve server response times, preload key assets, and optimize hero content.',
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
const targetCLS = Number(site.thresholds?.targetCLS || 0.1);
|
|
49
|
-
if (typeof pageSpeed.averageCLS === 'number' && pageSpeed.averageCLS > targetCLS) {
|
|
50
|
-
nextIssues.push({
|
|
51
|
-
fingerprint: `perf-cls-${pageSpeed.averageCLS}`,
|
|
52
|
-
ruleID: 'pagespeed-cls-high',
|
|
53
|
-
category: 'performance',
|
|
54
|
-
severity: pageSpeed.averageCLS > targetCLS * 2 ? 'high' : 'medium',
|
|
55
|
-
message: `Average CLS is ${pageSpeed.averageCLS}.`,
|
|
56
|
-
recommendation: 'Set explicit media dimensions and reduce layout shifts from dynamic UI elements.',
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return nextIssues;
|
|
60
|
-
};
|
|
61
13
|
async function handleSeoRunStream(payload, request) {
|
|
62
14
|
const body = (await request.json().catch(() => ({})));
|
|
63
15
|
const encoder = new TextEncoder();
|
|
@@ -84,173 +36,25 @@ async function handleSeoRunStream(payload, request) {
|
|
|
84
36
|
controller.close();
|
|
85
37
|
return;
|
|
86
38
|
}
|
|
87
|
-
const site = {
|
|
88
|
-
id: 1,
|
|
89
|
-
name: seoConfig.site.name,
|
|
90
|
-
domain: seoConfig.site.domain,
|
|
91
|
-
canonicalHost: seoConfig.site.canonicalHost,
|
|
92
|
-
sitemapURL: seoConfig.site.sitemapURL,
|
|
93
|
-
keyURLs: seoConfig.site.keyURLs.map((url) => ({ url })),
|
|
94
|
-
crawlSettings: {
|
|
95
|
-
maxPages: seoConfig.crawl.maxPages,
|
|
96
|
-
maxDepth: seoConfig.crawl.maxDepth,
|
|
97
|
-
requestTimeoutMs: seoConfig.crawl.requestTimeoutMs,
|
|
98
|
-
includePatterns: seoConfig.crawl.includePatterns.map((pattern) => ({ pattern })),
|
|
99
|
-
excludePatterns: seoConfig.crawl.excludePatterns.map((pattern) => ({ pattern })),
|
|
100
|
-
},
|
|
101
|
-
integrations: {
|
|
102
|
-
enablePageSpeed: seoConfig.integrations.enablePageSpeed,
|
|
103
|
-
enableSearchConsole: seoConfig.integrations.enableSearchConsole,
|
|
104
|
-
},
|
|
105
|
-
thresholds: {
|
|
106
|
-
targetLCPMs: seoConfig.thresholds.targetLCPMs,
|
|
107
|
-
targetCLS: seoConfig.thresholds.targetCLS,
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
const runLabel = `${site.name} SEO Snapshot ${new Date().toISOString()}`;
|
|
111
39
|
send('progress', { step: 'snapshot', message: 'Creating snapshot record...' });
|
|
112
|
-
|
|
113
|
-
collection: 'seo-snapshots',
|
|
114
|
-
data: {
|
|
115
|
-
runLabel,
|
|
116
|
-
runType: resolveRunType(body.runType),
|
|
117
|
-
status: 'pending',
|
|
118
|
-
startedAt: new Date().toISOString(),
|
|
119
|
-
},
|
|
120
|
-
overrideAccess: true,
|
|
121
|
-
});
|
|
122
|
-
send('progress', { step: 'crawl', message: 'Crawling site pages...' });
|
|
123
|
-
const crawl = await (0, crawler_1.crawlSiteForSEO)(site);
|
|
124
|
-
send('progress', {
|
|
125
|
-
step: 'crawl-complete',
|
|
126
|
-
message: `Found ${crawl.pages.length} pages`,
|
|
127
|
-
data: { pagesFound: crawl.pages.length },
|
|
128
|
-
});
|
|
129
|
-
send('progress', { step: 'checks', message: 'Running SEO checks on all pages...' });
|
|
130
|
-
const pageResults = crawl.pages.map((page) => {
|
|
131
|
-
const check = (0, checks_1.runSEOChecks)(page.url, page.html);
|
|
132
|
-
const score = (0, scoring_1.scoreSEOIssues)(check.issues);
|
|
133
|
-
return {
|
|
134
|
-
url: page.url,
|
|
135
|
-
path: page.path,
|
|
136
|
-
statusCode: page.statusCode,
|
|
137
|
-
check,
|
|
138
|
-
score,
|
|
139
|
-
};
|
|
140
|
-
});
|
|
141
|
-
send('progress', { step: 'checks-complete', message: 'SEO checks complete' });
|
|
142
|
-
send('progress', { step: 'pagespeed', message: 'Analyzing page performance...' });
|
|
143
|
-
const pageSpeedSummary = site.integrations?.enablePageSpeed !== false
|
|
144
|
-
? await (0, pagespeed_1.getPageSpeedSummary)(pageResults.map((page) => page.url))
|
|
145
|
-
: null;
|
|
146
|
-
if (pageSpeedSummary) {
|
|
147
|
-
send('progress', {
|
|
148
|
-
step: 'pagespeed-complete',
|
|
149
|
-
message: `Performance analysis complete (avg: ${pageSpeedSummary.averagePerformanceScore})`,
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
else {
|
|
153
|
-
send('progress', { step: 'pagespeed-skipped', message: 'PageSpeed analysis disabled' });
|
|
154
|
-
}
|
|
155
|
-
send('progress', { step: 'gsc', message: 'Syncing Google Search Console data...' });
|
|
156
|
-
const keywordVisibilitySync = await (0, gsc_1.syncGSCKeywordVisibility)({
|
|
40
|
+
await (0, runAudit_1.runSEOSnapshot)({
|
|
157
41
|
payload,
|
|
158
|
-
site,
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
step
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
: `Automated audit completed using ${providerAdapter.name} authority adapter.`;
|
|
175
|
-
const scores = {
|
|
176
|
-
metadata: average(pageResults.map((result) => result.score.metadata)),
|
|
177
|
-
indexability: average(pageResults.map((result) => result.score.indexability)),
|
|
178
|
-
structure: average(pageResults.map((result) => result.score.structure)),
|
|
179
|
-
links: average(pageResults.map((result) => result.score.links)),
|
|
180
|
-
media: average(pageResults.map((result) => result.score.media)),
|
|
181
|
-
structuredData: average(pageResults.map((result) => result.score.structuredData)),
|
|
182
|
-
performance: typeof pageSpeedSummary?.averagePerformanceScore === 'number'
|
|
183
|
-
? pageSpeedSummary.averagePerformanceScore
|
|
184
|
-
: average(pageResults.map((result) => result.score.performance)),
|
|
185
|
-
};
|
|
186
|
-
const overallScore = Math.round(scores.metadata * 0.2 +
|
|
187
|
-
scores.indexability * 0.2 +
|
|
188
|
-
scores.structure * 0.15 +
|
|
189
|
-
scores.links * 0.1 +
|
|
190
|
-
scores.media * 0.1 +
|
|
191
|
-
scores.structuredData * 0.1 +
|
|
192
|
-
scores.performance * 0.15);
|
|
193
|
-
send('progress', { step: 'saving', message: 'Saving results to database...' });
|
|
194
|
-
const batchSize = 10;
|
|
195
|
-
for (let i = 0; i < pageResults.length; i += batchSize) {
|
|
196
|
-
const batch = pageResults.slice(i, i + batchSize);
|
|
197
|
-
await Promise.all(batch.map((result) => payload.create({
|
|
198
|
-
collection: 'seo-page-results',
|
|
199
|
-
data: {
|
|
200
|
-
snapshot: snapshot.id,
|
|
201
|
-
url: result.url,
|
|
202
|
-
path: result.path,
|
|
203
|
-
statusCode: result.statusCode,
|
|
204
|
-
title: result.check.title,
|
|
205
|
-
metaDescription: result.check.metaDescription,
|
|
206
|
-
canonical: result.check.canonical,
|
|
207
|
-
robotsMeta: result.check.robotsMeta,
|
|
208
|
-
h1Count: result.check.h1Count,
|
|
209
|
-
internalLinks: result.check.internalLinks,
|
|
210
|
-
externalLinks: result.check.externalLinks,
|
|
211
|
-
imagesTotal: result.check.imagesTotal,
|
|
212
|
-
imagesMissingAlt: result.check.imagesMissingAlt,
|
|
213
|
-
structuredDataBlocks: result.check.structuredDataBlocks,
|
|
214
|
-
headingOrderIssues: result.check.headingOrderIssues,
|
|
215
|
-
scoreBreakdown: result.score,
|
|
216
|
-
overallScore: Math.round(result.score.metadata * 0.2 +
|
|
217
|
-
result.score.indexability * 0.2 +
|
|
218
|
-
result.score.structure * 0.15 +
|
|
219
|
-
result.score.links * 0.1 +
|
|
220
|
-
result.score.media * 0.1 +
|
|
221
|
-
result.score.structuredData * 0.1 +
|
|
222
|
-
result.score.performance * 0.15),
|
|
223
|
-
issues: result.check.issues,
|
|
224
|
-
checkedAt: new Date().toISOString(),
|
|
225
|
-
},
|
|
226
|
-
overrideAccess: true,
|
|
227
|
-
})));
|
|
228
|
-
}
|
|
229
|
-
await payload.update({
|
|
230
|
-
collection: 'seo-snapshots',
|
|
231
|
-
id: snapshot.id,
|
|
232
|
-
data: {
|
|
233
|
-
status: 'completed',
|
|
234
|
-
completedAt: new Date().toISOString(),
|
|
235
|
-
scores: { ...scores, overall: overallScore },
|
|
236
|
-
metrics: {
|
|
237
|
-
pagesCrawled: crawl.pages.length,
|
|
238
|
-
pagesChecked: pageResults.length,
|
|
239
|
-
avgLighthousePerformance: pageSpeedSummary?.averagePerformanceScore,
|
|
240
|
-
avgLCPMs: pageSpeedSummary?.averageLCPMs,
|
|
241
|
-
avgCLS: pageSpeedSummary?.averageCLS,
|
|
242
|
-
},
|
|
243
|
-
issueCounts,
|
|
244
|
-
summary: summaryText,
|
|
245
|
-
},
|
|
246
|
-
overrideAccess: true,
|
|
247
|
-
});
|
|
248
|
-
send('complete', {
|
|
249
|
-
message: 'Audit complete!',
|
|
250
|
-
data: {
|
|
251
|
-
pagesChecked: pageResults.length,
|
|
252
|
-
overallScore,
|
|
253
|
-
snapshotId: snapshot.id,
|
|
42
|
+
site: (0, integrationSettings_1.siteFromSeoConfig)(seoConfig),
|
|
43
|
+
seoConfig,
|
|
44
|
+
runType: resolveRunType(body.runType),
|
|
45
|
+
onProgress: async (step, message, data) => {
|
|
46
|
+
if (step === 'complete') {
|
|
47
|
+
send('complete', {
|
|
48
|
+
message,
|
|
49
|
+
data,
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
send('progress', {
|
|
54
|
+
step,
|
|
55
|
+
message,
|
|
56
|
+
data,
|
|
57
|
+
});
|
|
254
58
|
},
|
|
255
59
|
});
|
|
256
60
|
controller.close();
|
package/dist/api/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/api/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/api/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAY5D,wBAAsB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CA6ChG"}
|
package/dist/api/run.js
CHANGED
|
@@ -35,8 +35,9 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.handleSeoRun = handleSeoRun;
|
|
37
37
|
const auth_1 = require("../utilities/auth");
|
|
38
|
-
const runAudit_1 = require("../utilities/runAudit");
|
|
39
38
|
const index_1 = require("../index");
|
|
39
|
+
const integrationSettings_1 = require("../utilities/integrationSettings");
|
|
40
|
+
const runAudit_1 = require("../utilities/runAudit");
|
|
40
41
|
const resolveRunType = (value) => {
|
|
41
42
|
if (value === 'scheduled' || value === 'publish-triggered')
|
|
42
43
|
return value;
|
|
@@ -57,32 +58,10 @@ async function handleSeoRun(payload, request) {
|
|
|
57
58
|
return NextResponse.json({ error: 'SEO Audit plugin not configured' }, { status: 500 });
|
|
58
59
|
}
|
|
59
60
|
const body = (await request.json().catch(() => ({})));
|
|
60
|
-
const site = {
|
|
61
|
-
id: 1,
|
|
62
|
-
name: seoConfig.site.name,
|
|
63
|
-
domain: seoConfig.site.domain,
|
|
64
|
-
canonicalHost: seoConfig.site.canonicalHost,
|
|
65
|
-
sitemapURL: seoConfig.site.sitemapURL,
|
|
66
|
-
keyURLs: seoConfig.site.keyURLs.map(url => ({ url })),
|
|
67
|
-
crawlSettings: {
|
|
68
|
-
maxPages: seoConfig.crawl.maxPages,
|
|
69
|
-
maxDepth: seoConfig.crawl.maxDepth,
|
|
70
|
-
requestTimeoutMs: seoConfig.crawl.requestTimeoutMs,
|
|
71
|
-
includePatterns: seoConfig.crawl.includePatterns.map(pattern => ({ pattern })),
|
|
72
|
-
excludePatterns: seoConfig.crawl.excludePatterns.map(pattern => ({ pattern })),
|
|
73
|
-
},
|
|
74
|
-
integrations: {
|
|
75
|
-
enablePageSpeed: seoConfig.integrations.enablePageSpeed,
|
|
76
|
-
enableSearchConsole: seoConfig.integrations.enableSearchConsole,
|
|
77
|
-
},
|
|
78
|
-
thresholds: {
|
|
79
|
-
targetLCPMs: seoConfig.thresholds.targetLCPMs,
|
|
80
|
-
targetCLS: seoConfig.thresholds.targetCLS,
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
61
|
const result = await (0, runAudit_1.runSEOSnapshot)({
|
|
84
62
|
payload,
|
|
85
|
-
site,
|
|
63
|
+
site: (0, integrationSettings_1.siteFromSeoConfig)(seoConfig),
|
|
64
|
+
seoConfig,
|
|
86
65
|
runType: resolveRunType(body.runType),
|
|
87
66
|
});
|
|
88
67
|
return NextResponse.json({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SeoSnapshots.d.ts","sourceRoot":"","sources":["../../src/collections/SeoSnapshots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAG/C,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"SeoSnapshots.d.ts","sourceRoot":"","sources":["../../src/collections/SeoSnapshots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAA;AAG/C,eAAO,MAAM,YAAY,EAAE,gBA6J1B,CAAA"}
|
|
@@ -106,6 +106,25 @@ exports.SeoSnapshots = {
|
|
|
106
106
|
{ name: 'avgLighthousePerformance', type: 'number' },
|
|
107
107
|
{ name: 'avgLCPMs', type: 'number' },
|
|
108
108
|
{ name: 'avgCLS', type: 'number' },
|
|
109
|
+
{ name: 'cruxAvailable', type: 'checkbox' },
|
|
110
|
+
{
|
|
111
|
+
name: 'cruxSource',
|
|
112
|
+
type: 'select',
|
|
113
|
+
options: [
|
|
114
|
+
{ label: 'Origin', value: 'origin' },
|
|
115
|
+
{ label: 'URL', value: 'url' },
|
|
116
|
+
{ label: 'Mixed', value: 'mixed' },
|
|
117
|
+
{ label: 'None', value: 'none' },
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
{ name: 'cruxGoodLCPPct', type: 'number' },
|
|
121
|
+
{ name: 'cruxGoodINPPct', type: 'number' },
|
|
122
|
+
{ name: 'cruxGoodCLSPct', type: 'number' },
|
|
123
|
+
{ name: 'cruxP75LCPMs', type: 'number' },
|
|
124
|
+
{ name: 'cruxP75INPMs', type: 'number' },
|
|
125
|
+
{ name: 'cruxP75CLS', type: 'number' },
|
|
126
|
+
{ name: 'cruxSampleUrlsChecked', type: 'number' },
|
|
127
|
+
{ name: 'cruxSampleUrlsWithData', type: 'number' },
|
|
109
128
|
],
|
|
110
129
|
},
|
|
111
130
|
{
|
|
@@ -123,6 +142,13 @@ exports.SeoSnapshots = {
|
|
|
123
142
|
name: 'summary',
|
|
124
143
|
type: 'textarea',
|
|
125
144
|
},
|
|
145
|
+
{
|
|
146
|
+
name: 'integrationStatus',
|
|
147
|
+
type: 'json',
|
|
148
|
+
admin: {
|
|
149
|
+
readOnly: true,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
126
152
|
{
|
|
127
153
|
name: 'errorMessage',
|
|
128
154
|
type: 'textarea',
|
|
@@ -32,6 +32,16 @@ export type SEOMetrics = {
|
|
|
32
32
|
avgLighthousePerformance?: number | null;
|
|
33
33
|
avgLCPMs?: number | null;
|
|
34
34
|
avgCLS?: number | null;
|
|
35
|
+
cruxAvailable?: boolean | null;
|
|
36
|
+
cruxSource?: 'origin' | 'url' | 'mixed' | 'none' | null;
|
|
37
|
+
cruxGoodLCPPct?: number | null;
|
|
38
|
+
cruxGoodINPPct?: number | null;
|
|
39
|
+
cruxGoodCLSPct?: number | null;
|
|
40
|
+
cruxP75LCPMs?: number | null;
|
|
41
|
+
cruxP75INPMs?: number | null;
|
|
42
|
+
cruxP75CLS?: number | null;
|
|
43
|
+
cruxSampleUrlsChecked?: number | null;
|
|
44
|
+
cruxSampleUrlsWithData?: number | null;
|
|
35
45
|
};
|
|
36
46
|
export type SEOSnapshot = {
|
|
37
47
|
id: number | string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAA;AAE9E,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,cAAc,GACd,WAAW,GACX,OAAO,GACP,OAAO,GACP,gBAAgB,GAChB,aAAa,CAAA;AAEjB,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,wBAAwB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/components/types.ts"],"names":[],"mappings":"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"}
|