claude-plugin-wordpress-manager 2.4.0 → 2.6.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/.claude-plugin/plugin.json +10 -3
- package/CHANGELOG.md +42 -0
- package/agents/wp-content-strategist.md +104 -0
- package/docs/GUIDE.md +183 -23
- package/package.json +12 -3
- package/servers/wp-rest-bridge/build/tools/comments.d.ts +6 -6
- package/servers/wp-rest-bridge/build/tools/gsc.d.ts +3 -0
- package/servers/wp-rest-bridge/build/tools/gsc.js +354 -0
- package/servers/wp-rest-bridge/build/tools/index.d.ts +38 -38
- package/servers/wp-rest-bridge/build/tools/index.js +3 -0
- package/servers/wp-rest-bridge/build/tools/media.d.ts +2 -2
- package/servers/wp-rest-bridge/build/tools/multisite-sites.d.ts +2 -2
- package/servers/wp-rest-bridge/build/tools/plugin-repository.d.ts +1 -1
- package/servers/wp-rest-bridge/build/tools/search.d.ts +2 -2
- package/servers/wp-rest-bridge/build/tools/unified-content.d.ts +8 -8
- package/servers/wp-rest-bridge/build/tools/unified-taxonomies.d.ts +4 -4
- package/servers/wp-rest-bridge/build/tools/users.d.ts +6 -6
- package/servers/wp-rest-bridge/build/tools/wc-coupons.d.ts +1 -1
- package/servers/wp-rest-bridge/build/tools/wc-customers.d.ts +3 -3
- package/servers/wp-rest-bridge/build/tools/wc-orders.d.ts +4 -4
- package/servers/wp-rest-bridge/build/tools/wc-products.d.ts +8 -8
- package/servers/wp-rest-bridge/build/tools/wc-webhooks.d.ts +4 -4
- package/servers/wp-rest-bridge/build/wordpress.d.ts +5 -0
- package/servers/wp-rest-bridge/build/wordpress.js +39 -0
- package/servers/wp-rest-bridge/package.json +1 -0
- package/skills/wordpress-router/references/decision-tree.md +6 -2
- package/skills/wp-content/SKILL.md +1 -0
- package/skills/wp-content-attribution/SKILL.md +2 -0
- package/skills/wp-content-optimization/SKILL.md +172 -0
- package/skills/wp-content-optimization/references/content-freshness.md +234 -0
- package/skills/wp-content-optimization/references/headline-optimization.md +171 -0
- package/skills/wp-content-optimization/references/meta-optimization.md +243 -0
- package/skills/wp-content-optimization/references/readability-analysis.md +201 -0
- package/skills/wp-content-optimization/references/seo-content-scoring.md +245 -0
- package/skills/wp-content-optimization/scripts/content_optimization_inspect.mjs +237 -0
- package/skills/wp-monitoring/SKILL.md +1 -0
- package/skills/wp-programmatic-seo/SKILL.md +2 -0
- package/skills/wp-search-console/SKILL.md +121 -0
- package/skills/wp-search-console/references/competitor-gap-analysis.md +226 -0
- package/skills/wp-search-console/references/content-seo-feedback.md +181 -0
- package/skills/wp-search-console/references/gsc-setup.md +110 -0
- package/skills/wp-search-console/references/indexing-management.md +182 -0
- package/skills/wp-search-console/references/keyword-tracking.md +181 -0
- package/skills/wp-search-console/scripts/search_console_inspect.mjs +178 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* content_optimization_inspect.mjs — Detect content optimization readiness.
|
|
3
|
+
*
|
|
4
|
+
* Checks WordPress content volume, content age distribution, SEO plugins,
|
|
5
|
+
* readability plugins, GSC availability, and WooCommerce presence.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node content_optimization_inspect.mjs [--cwd=/path/to/project]
|
|
9
|
+
*
|
|
10
|
+
* Exit codes:
|
|
11
|
+
* 0 — content optimization readiness found
|
|
12
|
+
* 1 — no content optimization readiness found
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { readFileSync, existsSync, readdirSync } from 'node:fs';
|
|
16
|
+
import { join, resolve } from 'node:path';
|
|
17
|
+
import { argv, stdout, exit } from 'node:process';
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Helpers
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
function readFileSafe(filePath) {
|
|
24
|
+
try { return readFileSync(filePath, 'utf-8'); } catch { return null; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function existsSafe(filePath) {
|
|
28
|
+
try { return existsSync(filePath); } catch { return false; }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function globDir(dirPath) {
|
|
32
|
+
try { return readdirSync(dirPath); } catch { return []; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Detectors
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
function detectContent(cwd) {
|
|
40
|
+
const indicators = [];
|
|
41
|
+
|
|
42
|
+
// Check wp-content directory exists
|
|
43
|
+
if (!existsSafe(join(cwd, 'wp-content'))) {
|
|
44
|
+
return { has_content: false, indicators };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
indicators.push('wp-content directory exists');
|
|
48
|
+
|
|
49
|
+
// Check for uploads (indicator of content)
|
|
50
|
+
const uploads = globDir(join(cwd, 'wp-content', 'uploads'));
|
|
51
|
+
if (uploads.length > 0) {
|
|
52
|
+
indicators.push(`wp-content/uploads contains ${uploads.length} entries`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Check for themes presence
|
|
56
|
+
const themes = globDir(join(cwd, 'wp-content', 'themes'));
|
|
57
|
+
if (themes.length > 0) {
|
|
58
|
+
indicators.push(`${themes.length} theme(s) installed`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const hasContent = uploads.length > 0 || themes.length > 0;
|
|
62
|
+
return { has_content: hasContent, indicators };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function detectContentAge(cwd) {
|
|
66
|
+
const indicators = [];
|
|
67
|
+
const yearsFound = [];
|
|
68
|
+
|
|
69
|
+
const uploadsPath = join(cwd, 'wp-content', 'uploads');
|
|
70
|
+
if (!existsSafe(uploadsPath)) {
|
|
71
|
+
return { years_found: yearsFound, indicators };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const entries = globDir(uploadsPath);
|
|
75
|
+
const yearPattern = /^(20\d{2})$/;
|
|
76
|
+
|
|
77
|
+
for (const entry of entries) {
|
|
78
|
+
const match = entry.match(yearPattern);
|
|
79
|
+
if (match) {
|
|
80
|
+
yearsFound.push(parseInt(match[1], 10));
|
|
81
|
+
indicators.push(`upload directory found for year ${match[1]}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
yearsFound.sort();
|
|
86
|
+
|
|
87
|
+
if (yearsFound.length > 1) {
|
|
88
|
+
indicators.push(`content spans ${yearsFound.length} years (${yearsFound[0]}–${yearsFound[yearsFound.length - 1]})`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { years_found: yearsFound, indicators };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function detectSeoPlugins(cwd) {
|
|
95
|
+
const indicators = [];
|
|
96
|
+
const plugins = globDir(join(cwd, 'wp-content', 'plugins'));
|
|
97
|
+
|
|
98
|
+
const seoPlugins = [
|
|
99
|
+
{ dir: 'wordpress-seo', name: 'Yoast SEO' },
|
|
100
|
+
{ dir: 'seo-by-rank-math', name: 'RankMath' },
|
|
101
|
+
{ dir: 'all-in-one-seo-pack', name: 'AIOSEO' },
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
for (const plugin of plugins) {
|
|
105
|
+
const lower = plugin.toLowerCase();
|
|
106
|
+
for (const seo of seoPlugins) {
|
|
107
|
+
if (lower === seo.dir) {
|
|
108
|
+
indicators.push(`seo_plugin: ${seo.name} (${plugin})`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { found: indicators.length > 0, indicators };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function detectReadability(cwd) {
|
|
117
|
+
const indicators = [];
|
|
118
|
+
const plugins = globDir(join(cwd, 'wp-content', 'plugins'));
|
|
119
|
+
|
|
120
|
+
// Yoast and RankMath both include readability analysis
|
|
121
|
+
const readabilityPlugins = [
|
|
122
|
+
{ dir: 'wordpress-seo', name: 'Yoast SEO (readability analysis)' },
|
|
123
|
+
{ dir: 'seo-by-rank-math', name: 'RankMath (readability analysis)' },
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
for (const plugin of plugins) {
|
|
127
|
+
const lower = plugin.toLowerCase();
|
|
128
|
+
for (const rp of readabilityPlugins) {
|
|
129
|
+
if (lower === rp.dir) {
|
|
130
|
+
indicators.push(`readability_plugin: ${rp.name}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return { found: indicators.length > 0, indicators };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function detectGsc() {
|
|
139
|
+
const indicators = [];
|
|
140
|
+
let configured = false;
|
|
141
|
+
|
|
142
|
+
const raw = process.env.WP_SITES_CONFIG;
|
|
143
|
+
if (!raw) return { configured, indicators };
|
|
144
|
+
|
|
145
|
+
let sites;
|
|
146
|
+
try { sites = JSON.parse(raw); } catch { return { configured, indicators }; }
|
|
147
|
+
if (!Array.isArray(sites)) return { configured, indicators };
|
|
148
|
+
|
|
149
|
+
for (const site of sites) {
|
|
150
|
+
const label = site.name || site.url || 'unknown';
|
|
151
|
+
if (site.gsc_service_account_key) {
|
|
152
|
+
configured = true;
|
|
153
|
+
indicators.push(`gsc_service_account_key configured for ${label}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return { configured, indicators };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function detectWoocommerce(cwd) {
|
|
161
|
+
const indicators = [];
|
|
162
|
+
const plugins = globDir(join(cwd, 'wp-content', 'plugins'));
|
|
163
|
+
|
|
164
|
+
for (const plugin of plugins) {
|
|
165
|
+
if (plugin.toLowerCase() === 'woocommerce') {
|
|
166
|
+
indicators.push(`woocommerce plugin detected (${plugin})`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { found: indicators.length > 0, indicators };
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---------------------------------------------------------------------------
|
|
174
|
+
// Main
|
|
175
|
+
// ---------------------------------------------------------------------------
|
|
176
|
+
|
|
177
|
+
function main() {
|
|
178
|
+
const cwdArg = argv.find(a => a.startsWith('--cwd='));
|
|
179
|
+
const cwd = cwdArg ? resolve(cwdArg.split('=')[1]) : process.cwd();
|
|
180
|
+
|
|
181
|
+
const content = detectContent(cwd);
|
|
182
|
+
const contentAge = detectContentAge(cwd);
|
|
183
|
+
const seoPlugins = detectSeoPlugins(cwd);
|
|
184
|
+
const readability = detectReadability(cwd);
|
|
185
|
+
const gscAvailable = detectGsc();
|
|
186
|
+
const woocommerce = detectWoocommerce(cwd);
|
|
187
|
+
|
|
188
|
+
const found = content.has_content &&
|
|
189
|
+
(seoPlugins.found || readability.found || gscAvailable.configured);
|
|
190
|
+
|
|
191
|
+
const recommendations = [];
|
|
192
|
+
|
|
193
|
+
if (content.has_content) {
|
|
194
|
+
recommendations.push('Content detected — ready for AI-driven optimization analysis');
|
|
195
|
+
}
|
|
196
|
+
if (seoPlugins.found) {
|
|
197
|
+
recommendations.push('SEO plugin detected — headline and meta description optimization can use plugin data');
|
|
198
|
+
}
|
|
199
|
+
if (readability.found) {
|
|
200
|
+
recommendations.push('Readability analysis available — use wp-content-optimization for Flesch-Kincaid scoring');
|
|
201
|
+
}
|
|
202
|
+
if (gscAvailable.configured) {
|
|
203
|
+
recommendations.push('GSC configured — combine search data with content optimization for data-driven improvements');
|
|
204
|
+
}
|
|
205
|
+
if (woocommerce.found) {
|
|
206
|
+
recommendations.push('WooCommerce detected — prioritize optimization of high-revenue content');
|
|
207
|
+
}
|
|
208
|
+
if (contentAge.years_found.length > 1) {
|
|
209
|
+
recommendations.push('Content spans multiple years — run Content Freshness Audit to identify stale content');
|
|
210
|
+
}
|
|
211
|
+
if (!content.has_content && !seoPlugins.found && !readability.found && !gscAvailable.configured) {
|
|
212
|
+
recommendations.push('No content or optimization tools detected — create content first, then use wp-content-optimization');
|
|
213
|
+
}
|
|
214
|
+
if (content.has_content && seoPlugins.found && gscAvailable.configured) {
|
|
215
|
+
recommendations.push('Full optimization stack ready — use wp-content-optimization for comprehensive content triage');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const report = {
|
|
219
|
+
tool: 'content_optimization_inspect',
|
|
220
|
+
version: '1.0.0',
|
|
221
|
+
timestamp: new Date().toISOString(),
|
|
222
|
+
cwd,
|
|
223
|
+
found,
|
|
224
|
+
content,
|
|
225
|
+
content_age: contentAge,
|
|
226
|
+
seo_plugins: seoPlugins,
|
|
227
|
+
readability,
|
|
228
|
+
gsc_available: gscAvailable,
|
|
229
|
+
woocommerce,
|
|
230
|
+
recommendations,
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
234
|
+
exit(found ? 0 : 1);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
main();
|
|
@@ -129,3 +129,4 @@ See `references/fleet-monitoring.md`
|
|
|
129
129
|
- **`wp-security`** — hardening procedures triggered by monitoring alerts
|
|
130
130
|
- **`wp-performance`** — optimization actions based on performance trends
|
|
131
131
|
- **`wp-cicd`** — CI/CD quality gates that complement monitoring (pre-deploy checks)
|
|
132
|
+
- **`wp-search-console`** — add GSC search performance checks to periodic SEO monitoring
|
|
@@ -95,3 +95,5 @@ The script checks headless frontend presence, SEO plugins, content volume, custo
|
|
|
95
95
|
- `wp-rest-api` — REST API endpoints for content CRUD
|
|
96
96
|
- `wp-content` — content management fundamentals
|
|
97
97
|
- `wp-content-repurposing` — transform existing content into new formats
|
|
98
|
+
- `wp-search-console` — monitor performance of generated pages via GSC keyword tracking and indexing status
|
|
99
|
+
- `wp-content-optimization` — optimize programmatic page templates for headlines, readability, and SEO scoring
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wp-search-console
|
|
3
|
+
description: This skill should be used when the user asks about "Google Search Console",
|
|
4
|
+
"GSC", "keyword tracking", "keyword rankings", "search analytics",
|
|
5
|
+
"indexing status", "URL inspection", "sitemap management",
|
|
6
|
+
"search performance", "SEO feedback", "content SEO",
|
|
7
|
+
"competitor gap analysis", "keyword gap", or mentions monitoring
|
|
8
|
+
WordPress site search performance.
|
|
9
|
+
version: 1.0.0
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# WordPress Search Console Skill
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Google Search Console connects WordPress content to Google Search data via 8 MCP tools. These tools enable keyword tracking, indexing management, sitemap operations, and search performance analysis directly from the WordPress authoring environment. By bridging GSC data with WordPress content, you can identify optimization opportunities, monitor indexing health, and build data-driven content strategies.
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
- User wants to check how their WordPress pages perform in Google Search
|
|
21
|
+
- User needs to track keyword rankings and position changes over time
|
|
22
|
+
- User asks about indexing status or why a page is not appearing in Google
|
|
23
|
+
- User wants to submit or manage XML sitemaps
|
|
24
|
+
- User needs search analytics data (clicks, impressions, CTR, average position)
|
|
25
|
+
- User asks about content SEO improvements based on search data
|
|
26
|
+
- User wants to identify keyword gaps or content opportunities
|
|
27
|
+
- User needs to inspect a specific URL for crawl and indexing details
|
|
28
|
+
|
|
29
|
+
## Decision Tree
|
|
30
|
+
|
|
31
|
+
1. **What aspect of Search Console?**
|
|
32
|
+
- "setup" / "connect GSC" / "service account" / "verify site" → GSC setup (Section 1)
|
|
33
|
+
- "keyword tracking" / "rankings" / "position" / "top queries" → Keyword tracking (Section 2)
|
|
34
|
+
- "indexing" / "URL inspection" / "sitemap" / "crawl" / "not indexed" → Indexing management (Section 3)
|
|
35
|
+
- "content SEO" / "underperforming pages" / "content refresh" / "optimize title" → Content SEO feedback (Section 4)
|
|
36
|
+
- "competitor gap" / "keyword gap" / "content opportunities" / "missing keywords" → Competitor gap analysis (Section 5)
|
|
37
|
+
|
|
38
|
+
2. **Run detection first:**
|
|
39
|
+
```bash
|
|
40
|
+
node skills/wp-search-console/scripts/search_console_inspect.mjs [--cwd=/path/to/project]
|
|
41
|
+
```
|
|
42
|
+
This identifies configured GSC credentials and verified sites.
|
|
43
|
+
|
|
44
|
+
## Service Overview
|
|
45
|
+
|
|
46
|
+
| Service | Tools | Auth Type | Use Case |
|
|
47
|
+
|---------|-------|-----------|----------|
|
|
48
|
+
| Google Search Console | 8 tools (`gsc_*`) | Service Account JSON | Search analytics, indexing, sitemaps |
|
|
49
|
+
|
|
50
|
+
## Sections
|
|
51
|
+
|
|
52
|
+
### Section 1: GSC Setup
|
|
53
|
+
See `references/gsc-setup.md`
|
|
54
|
+
- Service account creation in Google Cloud Console
|
|
55
|
+
- JSON key file configuration
|
|
56
|
+
- WP_SITES_CONFIG setup with gsc_service_account_key and gsc_site_url
|
|
57
|
+
- Site verification and permissions
|
|
58
|
+
|
|
59
|
+
### Section 2: Keyword Tracking
|
|
60
|
+
See `references/keyword-tracking.md`
|
|
61
|
+
- Using gsc_search_analytics and gsc_top_queries for keyword monitoring
|
|
62
|
+
- Date range and dimension filters
|
|
63
|
+
- Tracking position changes over time
|
|
64
|
+
- Query-level analysis (clicks, impressions, CTR, average position)
|
|
65
|
+
|
|
66
|
+
### Section 3: Indexing Management
|
|
67
|
+
See `references/indexing-management.md`
|
|
68
|
+
- Using gsc_inspect_url for indexing status checks
|
|
69
|
+
- Sitemap operations (list, submit, delete)
|
|
70
|
+
- Monitoring crawl coverage
|
|
71
|
+
- Handling indexing issues and bulk URL inspection
|
|
72
|
+
|
|
73
|
+
### Section 4: Content SEO Feedback
|
|
74
|
+
See `references/content-seo-feedback.md`
|
|
75
|
+
- Connecting search data to WordPress content strategy
|
|
76
|
+
- Identifying underperforming pages with gsc_page_performance
|
|
77
|
+
- Content refresh strategies based on declining metrics
|
|
78
|
+
- Title and meta description optimization from search data
|
|
79
|
+
|
|
80
|
+
### Section 5: Competitor Gap Analysis
|
|
81
|
+
See `references/competitor-gap-analysis.md`
|
|
82
|
+
- Identifying keyword gaps using search analytics data
|
|
83
|
+
- Analyzing query coverage vs potential queries
|
|
84
|
+
- Finding content opportunities from query data
|
|
85
|
+
- Cross-referencing with WordPress content inventory
|
|
86
|
+
|
|
87
|
+
## Reference Files
|
|
88
|
+
|
|
89
|
+
| File | Content |
|
|
90
|
+
|------|---------|
|
|
91
|
+
| `references/gsc-setup.md` | Service account creation, JSON key config, site verification |
|
|
92
|
+
| `references/keyword-tracking.md` | Search analytics queries, position monitoring, dashboards |
|
|
93
|
+
| `references/indexing-management.md` | URL inspection, sitemap management, crawl coverage |
|
|
94
|
+
| `references/content-seo-feedback.md` | Page performance, content refresh, title optimization |
|
|
95
|
+
| `references/competitor-gap-analysis.md` | Keyword gaps, content opportunities, position strategies |
|
|
96
|
+
|
|
97
|
+
## MCP Tools
|
|
98
|
+
|
|
99
|
+
| Tool | Description |
|
|
100
|
+
|------|-------------|
|
|
101
|
+
| `gsc_list_sites` | List all verified sites in Google Search Console |
|
|
102
|
+
| `gsc_search_analytics` | Query search analytics data with dimensions and filters |
|
|
103
|
+
| `gsc_inspect_url` | Inspect a URL for indexing status and crawl details |
|
|
104
|
+
| `gsc_list_sitemaps` | List submitted sitemaps and their status |
|
|
105
|
+
| `gsc_submit_sitemap` | Submit a new sitemap URL to GSC |
|
|
106
|
+
| `gsc_delete_sitemap` | Remove a sitemap from GSC |
|
|
107
|
+
| `gsc_top_queries` | Get top search queries with clicks, impressions, CTR, position |
|
|
108
|
+
| `gsc_page_performance` | Get page-level performance data with search metrics |
|
|
109
|
+
|
|
110
|
+
## Recommended Agent
|
|
111
|
+
|
|
112
|
+
Use the **`wp-content-strategist`** agent for SEO feedback loops and content optimization workflows that combine Search Console data with WordPress content management.
|
|
113
|
+
|
|
114
|
+
## Related Skills
|
|
115
|
+
|
|
116
|
+
- **`wp-programmatic-seo`** — generate SEO-optimized content at scale using search data
|
|
117
|
+
- **`wp-content-attribution`** — track content sources and attribute search traffic
|
|
118
|
+
- **`wp-monitoring`** — monitor site health metrics alongside search performance
|
|
119
|
+
- **`wp-social-email`** — distribute optimized content across social and email channels
|
|
120
|
+
- **`wp-content`** — create and manage WordPress content informed by search analytics
|
|
121
|
+
- **`wp-content-optimization`** — use GSC data as input for AI-driven content optimization and triage
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Competitor Gap Analysis
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Competitor gap analysis uses Google Search Console data to identify keyword opportunities your WordPress site is missing. By analyzing your query coverage, position distribution, and content inventory, you can find topics where you have search visibility but no dedicated content, or where competitors likely rank for queries you do not yet target.
|
|
6
|
+
|
|
7
|
+
## Identifying Keyword Gaps
|
|
8
|
+
|
|
9
|
+
### Step 1: Export your full query coverage
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Tool: gsc_search_analytics
|
|
13
|
+
Params:
|
|
14
|
+
site_url: "https://example.com/"
|
|
15
|
+
start_date: "2026-02-01"
|
|
16
|
+
end_date: "2026-02-28"
|
|
17
|
+
dimensions: ["query"]
|
|
18
|
+
row_limit: 5000
|
|
19
|
+
Returns: Array of all queries with clicks, impressions, ctr, position
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This gives you every query Google associates with your site. Sort by impressions to see which topics generate the most search visibility.
|
|
23
|
+
|
|
24
|
+
### Step 2: Map queries to content
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
Tool: gsc_search_analytics
|
|
28
|
+
Params:
|
|
29
|
+
site_url: "https://example.com/"
|
|
30
|
+
start_date: "2026-02-01"
|
|
31
|
+
end_date: "2026-02-28"
|
|
32
|
+
dimensions: ["query", "page"]
|
|
33
|
+
row_limit: 5000
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This maps each query to the page that ranks for it. Look for:
|
|
37
|
+
- **Queries without a dedicated page** — a query matches a generic page rather than a focused article
|
|
38
|
+
- **Multiple queries pointing to one page** — the page may be covering too many topics and could be split
|
|
39
|
+
- **Queries with position > 20** — you appear in results but have no strong content to compete
|
|
40
|
+
|
|
41
|
+
### Step 3: Identify content gaps
|
|
42
|
+
|
|
43
|
+
Cross-reference your queries with your WordPress content inventory:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
# Get all published content
|
|
47
|
+
Step 1: wp_list_posts status="publish" per_page=100 → Array of posts with titles and URLs
|
|
48
|
+
|
|
49
|
+
# Get all queries with page mapping
|
|
50
|
+
Step 2: gsc_search_analytics dimensions=["query", "page"] row_limit=5000
|
|
51
|
+
|
|
52
|
+
# Compare: queries that map to pages not optimized for them = content gaps
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Analyzing Query Coverage
|
|
56
|
+
|
|
57
|
+
### Position distribution analysis
|
|
58
|
+
|
|
59
|
+
Categorize your queries by position to understand coverage quality:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Tool: gsc_search_analytics
|
|
63
|
+
Params:
|
|
64
|
+
site_url: "https://example.com/"
|
|
65
|
+
start_date: "2026-02-01"
|
|
66
|
+
end_date: "2026-02-28"
|
|
67
|
+
dimensions: ["query"]
|
|
68
|
+
row_limit: 5000
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Group results by position ranges:
|
|
72
|
+
|
|
73
|
+
| Position Range | Category | Strategy |
|
|
74
|
+
|----------------|----------|----------|
|
|
75
|
+
| 1-3 | Dominant | Protect — monitor and update regularly |
|
|
76
|
+
| 4-10 | Competitive | Optimize — content refresh, internal links, backlinks |
|
|
77
|
+
| 11-20 | Striking distance | Target — create supporting content, build topic clusters |
|
|
78
|
+
| 21-50 | Weak presence | Evaluate — is the content worth investing in? |
|
|
79
|
+
| 50+ | Minimal visibility | Decide — create new dedicated content or abandon |
|
|
80
|
+
|
|
81
|
+
### Topic cluster gaps
|
|
82
|
+
|
|
83
|
+
Group related queries into topic clusters to find areas where your coverage is incomplete:
|
|
84
|
+
|
|
85
|
+
1. Export all queries with `gsc_search_analytics`
|
|
86
|
+
2. Group queries by root topic (e.g., "wordpress seo", "wordpress performance", "wordpress security")
|
|
87
|
+
3. Count unique queries per topic and average position per topic
|
|
88
|
+
4. Topics with few queries or high average position are underserved
|
|
89
|
+
|
|
90
|
+
## Finding Content Opportunities
|
|
91
|
+
|
|
92
|
+
### High-impression, no-click queries
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Tool: gsc_search_analytics
|
|
96
|
+
Params:
|
|
97
|
+
site_url: "https://example.com/"
|
|
98
|
+
start_date: "2026-02-01"
|
|
99
|
+
end_date: "2026-02-28"
|
|
100
|
+
dimensions: ["query", "page"]
|
|
101
|
+
row_limit: 1000
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Filter for queries where `impressions > 100` and `clicks == 0`. These are searches where Google shows your site but users never click — likely because:
|
|
105
|
+
- Your page does not match the query intent
|
|
106
|
+
- Your title and description are not compelling for that query
|
|
107
|
+
- You rank too low (position > 20) for the query to generate clicks
|
|
108
|
+
|
|
109
|
+
For each opportunity, decide whether to:
|
|
110
|
+
- **Optimize the existing page** for that query (if the topic is related)
|
|
111
|
+
- **Create a new dedicated page** targeting that query (if the topic is distinct)
|
|
112
|
+
|
|
113
|
+
### Question-based queries
|
|
114
|
+
|
|
115
|
+
Filter queries that start with question words (what, how, why, when, where, which, can, does, is):
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Tool: gsc_search_analytics
|
|
119
|
+
Params:
|
|
120
|
+
site_url: "https://example.com/"
|
|
121
|
+
start_date: "2026-02-01"
|
|
122
|
+
end_date: "2026-02-28"
|
|
123
|
+
dimensions: ["query"]
|
|
124
|
+
dimension_filter_groups:
|
|
125
|
+
- filters:
|
|
126
|
+
- dimension: "query"
|
|
127
|
+
operator: "contains"
|
|
128
|
+
expression: "how to"
|
|
129
|
+
row_limit: 200
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Question queries map directly to FAQ content, how-to guides, and tutorial posts. If you appear for these queries but don't have dedicated content, create:
|
|
133
|
+
- FAQ sections on existing pages
|
|
134
|
+
- Standalone how-to articles
|
|
135
|
+
- Comprehensive guides that answer multiple related questions
|
|
136
|
+
|
|
137
|
+
### Long-tail opportunities
|
|
138
|
+
|
|
139
|
+
Queries with 4+ words are typically long-tail keywords with lower competition:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
Tool: gsc_search_analytics
|
|
143
|
+
Params:
|
|
144
|
+
site_url: "https://example.com/"
|
|
145
|
+
start_date: "2026-02-01"
|
|
146
|
+
end_date: "2026-02-28"
|
|
147
|
+
dimensions: ["query"]
|
|
148
|
+
row_limit: 2000
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Filter for queries containing 4+ words with `impressions > 20`. Long-tail keywords often have:
|
|
152
|
+
- Higher conversion intent
|
|
153
|
+
- Lower competition
|
|
154
|
+
- More specific content requirements
|
|
155
|
+
|
|
156
|
+
Create focused content addressing the exact long-tail query.
|
|
157
|
+
|
|
158
|
+
## Position Improvement Strategies
|
|
159
|
+
|
|
160
|
+
### Strategy 1: Topic clusters
|
|
161
|
+
|
|
162
|
+
For queries where you rank 11-20, build topic clusters:
|
|
163
|
+
|
|
164
|
+
1. Identify the core topic from your query data
|
|
165
|
+
2. Create a **pillar page** — comprehensive guide covering the broad topic
|
|
166
|
+
3. Create **cluster pages** — focused articles on subtopics
|
|
167
|
+
4. **Interlink** all cluster pages to the pillar and vice versa
|
|
168
|
+
5. Monitor position changes with `gsc_search_analytics` over 4-8 weeks
|
|
169
|
+
|
|
170
|
+
### Strategy 2: Content depth expansion
|
|
171
|
+
|
|
172
|
+
For queries where you rank 4-10 but cannot break into top 3:
|
|
173
|
+
|
|
174
|
+
1. Analyze the query with `gsc_search_analytics` filtered by the specific query
|
|
175
|
+
2. Fetch the ranking page with `wp_get_post`
|
|
176
|
+
3. Expand the content:
|
|
177
|
+
- Add 500-1000 words of additional depth
|
|
178
|
+
- Include data, statistics, or original research
|
|
179
|
+
- Add images, tables, or diagrams
|
|
180
|
+
- Add expert quotes or citations
|
|
181
|
+
4. Update via `wp_update_post`
|
|
182
|
+
|
|
183
|
+
### Strategy 3: Internal link building
|
|
184
|
+
|
|
185
|
+
Boost underperforming pages with strategic internal links:
|
|
186
|
+
|
|
187
|
+
1. Identify pages ranking 11-30 for valuable queries
|
|
188
|
+
2. Find high-authority pages on your site (top performers from `gsc_page_performance`)
|
|
189
|
+
3. Add contextual internal links from high-authority pages to underperforming pages
|
|
190
|
+
4. Use the target query as anchor text (naturally, not forced)
|
|
191
|
+
|
|
192
|
+
## Cross-Referencing with WordPress Content
|
|
193
|
+
|
|
194
|
+
### Audit workflow
|
|
195
|
+
|
|
196
|
+
Complete gap analysis workflow combining GSC and WordPress data:
|
|
197
|
+
|
|
198
|
+
1. **Export all queries**: `gsc_search_analytics` with `dimensions: ["query"]`, `row_limit: 5000`
|
|
199
|
+
2. **Export all pages**: `gsc_page_performance` with `row_limit: 500`
|
|
200
|
+
3. **List WordPress content**: `wp_list_posts` with `status: "publish"`
|
|
201
|
+
4. **Map coverage**: For each WordPress post, check if it has GSC data
|
|
202
|
+
5. **Find orphans**: WordPress posts with no GSC impressions may have indexing or quality issues
|
|
203
|
+
6. **Find gaps**: Queries without a dedicated WordPress post are content opportunities
|
|
204
|
+
|
|
205
|
+
### Priority scoring
|
|
206
|
+
|
|
207
|
+
Score content opportunities by potential impact:
|
|
208
|
+
|
|
209
|
+
| Factor | Weight | Measurement |
|
|
210
|
+
|--------|--------|-------------|
|
|
211
|
+
| Impressions | High | More impressions = more potential traffic |
|
|
212
|
+
| Current position | Medium | Closer to page 1 = easier to improve |
|
|
213
|
+
| CTR gap | Medium | Low CTR vs expected = quick win with title optimization |
|
|
214
|
+
| Competition | Low | Long-tail queries typically have less competition |
|
|
215
|
+
| Business relevance | High | Queries related to products/services have higher value |
|
|
216
|
+
|
|
217
|
+
## Best Practices
|
|
218
|
+
|
|
219
|
+
- **Regular cadence**: Run gap analysis monthly to catch new opportunities as query landscape evolves
|
|
220
|
+
- **Focus on intent**: Not all queries are worth targeting; prioritize queries that align with your content goals and business objectives
|
|
221
|
+
- **Quality over quantity**: One comprehensive article targeting a cluster of related queries outperforms five thin articles each targeting a single query
|
|
222
|
+
- **Track outcomes**: After creating content for identified gaps, monitor its performance in GSC after 4-8 weeks
|
|
223
|
+
- **Avoid keyword cannibalization**: Before creating new content, check if an existing page already targets the same query cluster
|
|
224
|
+
- **Use search data directionally**: GSC data shows what Google associates with your site, not what your competitors rank for; use it as a map of your current footprint and expand from there
|
|
225
|
+
- **Combine with external tools**: For true competitive analysis (what competitors rank for that you do not), supplement GSC data with third-party tools like Ahrefs, SEMrush, or Moz
|
|
226
|
+
- **Content calendar integration**: Feed identified opportunities into your WordPress editorial calendar for systematic execution
|