seo-intel 1.4.5 → 1.4.7
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/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/server.js +43 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.7 (2026-04-09)
|
|
4
|
+
|
|
5
|
+
### Export: profiles are actions only
|
|
6
|
+
- Removed schemas from all export profiles — pure inventory, not actionable
|
|
7
|
+
- "No schema" issues already surfaced in technical section
|
|
8
|
+
- Raw Full Export (ZIP) still includes everything for data access
|
|
9
|
+
|
|
10
|
+
## 1.4.6 (2026-04-09)
|
|
11
|
+
|
|
12
|
+
### Export: rich actionable content
|
|
13
|
+
- Insights export now renders type-specific tables (quick wins show issue + fix + impact, keyword gaps show coverage, etc.)
|
|
14
|
+
- Schema markup export scoped to own site only — no competitor schema dumps
|
|
15
|
+
- SKILL.md updated with export profiles documentation
|
|
16
|
+
|
|
3
17
|
## 1.4.5 (2026-04-09)
|
|
4
18
|
|
|
5
19
|
### Export: actionable summaries only
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -611,7 +611,7 @@ async function handleRequest(req, res) {
|
|
|
611
611
|
// ── Profile definitions: which sections + which insight types matter ──
|
|
612
612
|
const PROFILES = {
|
|
613
613
|
dev: {
|
|
614
|
-
sections: ['technical', '
|
|
614
|
+
sections: ['technical', 'links', 'headings', 'watch', 'insights'],
|
|
615
615
|
insightTypes: ['technical_gap', 'quick_win', 'site_watch'],
|
|
616
616
|
label: 'Developer',
|
|
617
617
|
},
|
|
@@ -827,12 +827,7 @@ async function handleRequest(req, res) {
|
|
|
827
827
|
}
|
|
828
828
|
return issues;
|
|
829
829
|
}
|
|
830
|
-
case 'schemas':
|
|
831
|
-
if (!Array.isArray(data) || prof !== 'dev') return data;
|
|
832
|
-
// Dev: pages missing schema are more useful — but we only have pages WITH schema here
|
|
833
|
-
// So return all (schema gaps come from technical section's has_schema=false)
|
|
834
|
-
return data;
|
|
835
|
-
}
|
|
830
|
+
case 'schemas': return data; // raw only — not in any profile
|
|
836
831
|
case 'aeo': {
|
|
837
832
|
if (!Array.isArray(data)) return data;
|
|
838
833
|
if (prof === 'content') {
|
|
@@ -905,9 +900,47 @@ async function handleRequest(req, res) {
|
|
|
905
900
|
for (const r of data) { (grouped[r._type] ||= []).push(r); }
|
|
906
901
|
for (const [type, items] of Object.entries(grouped)) {
|
|
907
902
|
md += `### ${type.replace(/_/g, ' ')} (${items.length})\n\n`;
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
903
|
+
switch (type) {
|
|
904
|
+
case 'quick_win':
|
|
905
|
+
md += '| Page | Issue | Fix | Impact |\n|------|-------|-----|--------|\n';
|
|
906
|
+
for (const i of items) md += `| ${i.page || ''} | ${i.issue || ''} | ${i.fix || ''} | ${i.impact || ''} |\n`;
|
|
907
|
+
break;
|
|
908
|
+
case 'keyword_gap':
|
|
909
|
+
md += '| Keyword | Your Coverage | Competitor Coverage |\n|---------|--------------|--------------------|\n';
|
|
910
|
+
for (const i of items) md += `| ${i.keyword || ''} | ${i.your_coverage || i.target_count || 'none'} | ${i.competitor_coverage || i.competitor_count || ''} |\n`;
|
|
911
|
+
break;
|
|
912
|
+
case 'long_tail':
|
|
913
|
+
md += '| Phrase | Parent Keyword | Opportunity |\n|-------|----------------|-------------|\n';
|
|
914
|
+
for (const i of items) md += `| ${i.phrase || ''} | ${i.parent || i.keyword || ''} | ${i.opportunity || i.rationale || ''} |\n`;
|
|
915
|
+
break;
|
|
916
|
+
case 'new_page':
|
|
917
|
+
md += '| Title | Target Keyword | Rationale |\n|-------|----------------|----------|\n';
|
|
918
|
+
for (const i of items) md += `| ${i.title || ''} | ${i.target_keyword || ''} | ${i.rationale || ''} |\n`;
|
|
919
|
+
break;
|
|
920
|
+
case 'content_gap':
|
|
921
|
+
md += '| Topic | Gap | Suggestion |\n|-------|-----|------------|\n';
|
|
922
|
+
for (const i of items) md += `| ${i.topic || ''} | ${i.gap || ''} | ${i.suggestion || ''} |\n`;
|
|
923
|
+
break;
|
|
924
|
+
case 'technical_gap':
|
|
925
|
+
md += '| Issue | Affected | Recommendation |\n|-------|----------|----------------|\n';
|
|
926
|
+
for (const i of items) md += `| ${i.gap || i.issue || ''} | ${i.affected || i.pages || ''} | ${i.recommendation || i.fix || ''} |\n`;
|
|
927
|
+
break;
|
|
928
|
+
case 'citability_gap':
|
|
929
|
+
md += '| URL | Score | Weakest Signals |\n|-----|-------|----------------|\n';
|
|
930
|
+
for (const i of items) md += `| ${i.url || ''} | ${i.score ?? ''} | ${i.weak_signals || ''} |\n`;
|
|
931
|
+
break;
|
|
932
|
+
case 'keyword_inventor':
|
|
933
|
+
md += '| Phrase | Cluster | Search Potential |\n|-------|---------|------------------|\n';
|
|
934
|
+
for (const i of items) md += `| ${i.phrase || ''} | ${i.cluster || ''} | ${i.potential || i.volume || ''} |\n`;
|
|
935
|
+
break;
|
|
936
|
+
case 'site_watch':
|
|
937
|
+
md += '| URL | Event | Details |\n|-----|-------|--------|\n';
|
|
938
|
+
for (const i of items) md += `| ${i.url || ''} | ${i.event_type || ''} | ${i.details || ''} |\n`;
|
|
939
|
+
break;
|
|
940
|
+
default:
|
|
941
|
+
for (const i of items) {
|
|
942
|
+
md += `- ${i.phrase || i.keyword || i.title || i.page || i.message || JSON.stringify(i).slice(0, 120)}\n`;
|
|
943
|
+
}
|
|
911
944
|
}
|
|
912
945
|
md += '\n';
|
|
913
946
|
}
|