Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Batch update Yoast SEO metadata (titles, descriptions, focus keyphrases) in WordPress via GraphQL. Use when the user wants to update SEO metadata, optimize titles, fix meta descriptions, or manage Yoast SEO fields across multiple posts. Supports preview mode, progress tracking, and resume capability.
.claude/skills/nicepkg-seo-wordpress-manager/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | -34% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 18% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 0% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 0% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 4% | 0% |
This skill manages Yoast SEO metadata in WordPress sites via the WPGraphQL API. It enables batch updates of:
Add this to your theme's functions.php to enable mutations:
php// Enable Yoast SEO mutations via WPGraphQL add_action('graphql_register_types', function() { register_graphql_mutation('updatePostSeo', [ 'inputFields' => [ 'postId' => ['type' => 'Int', 'description' => 'Post ID'], 'title' => ['type' => 'String', 'description' => 'SEO Title'], 'metaDesc' => ['type' => 'String', 'description' => 'Meta Description'], 'focusKeyphrase' => ['type' => 'String', 'description' => 'Focus Keyphrase'], ], 'outputFields' => [ 'success' => ['type' => 'Boolean'], 'post' => ['type' => 'Post'], ], 'mutateAndGetPayload' => function($input) { $post_id = absint($input['postId']); if (!current_user_can('edit_post', $post_id)) { throw new \GraphQL\Error\UserError('You do not have permission to edit this post.'); } if (isset($input['title'])) { update_post_meta($post_id, '_yoast_wpseo_title', sanitize_text_field($input['title'])); } if (isset($input['metaDesc'])) { update_post_meta($post_id, '_yoast_wpseo_metadesc', sanitize_textarea_field($input['metaDesc'])); } if (isset($input['focusKeyphrase'])) { update_post_meta($post_id, '_yoast_wpseo_focuskw', sanitize_text_field($input['focusKeyphrase'])); } return [ 'success' => true, 'post' => get_post($post_id), ]; } ]); });
Create a config.json in the skill directory:
json{ "wordpress": { "graphql_url": "https://your-site.com/graphql", "username": "your-username", "app_password": "your-app-password" }, "batch": { "size": 10, "delay_seconds": 1 }, "state_file": "./seo_update_progress.json" }
Or use environment variables:
WP_GRAPHQL_URLWP_USERNAMEWP_APP_PASSWORDbashpython scripts/analyze_seo.py --all --output analysis.json
This fetches posts and identifies SEO issues (missing titles, too long descriptions, etc.). Output includes instructions for Claude to generate optimized SEO content.
Claude analyzes the analysis.json output and generates a changes.json file with:
bashpython scripts/preview_changes.py --input changes.json
bashpython scripts/yoast_batch_updater.py --input changes.json --apply
bashpython scripts/yoast_batch_updater.py --resume
The skill expects a JSON file with changes:
json{ "updates": [ { "post_id": 123, "post_title": "Original Post Title", "current": { "seo_title": "Old Title | Site Name", "meta_desc": "Old description" }, "new": { "seo_title": "New Optimized Title | Site Name", "meta_desc": "New compelling meta description under 160 chars" } } ] }
The skill produces:
User: "Update the meta descriptions for all posts in the 'tutorials' category to be more compelling"
Claude will:
analyze_seo.py to fetch posts and identify SEO issueschanges.json file with the improvementspreview_changes.py to show before/after comparisonyoast_batch_updater.py --apply to apply changes| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 14,990 | 9,305 | -38% | 1 | 1 | 0% | 2,514 | 2,075 | -17% | 0 | 0 | — |
case-02 | fail→fail | 11,737 | 5,859 | -50% | 1 | 1 | 0% | 1,931 | 1,681 | -13% | 0 | 0 | — |
case-03 | fail→pass | 23,640 | 7,784 | -67% | 1 | 1 | 0% | 4,285 | 2,832 | -34% | 0 | 0 | — |
case-04 | fail→pass | 13,969 | 8,979 | -36% | 1 | 1 | 0% | 2,843 | 3,352 | +18% | 0 | 0 | — |
case-18 | pass→pass | 7,149 | 2,969 | -58% | 1 | 1 | 0% | 1,183 | 1,804 | +52% | 0 | 0 | — |
case-05 | pass→pass | 5,420 | 2,580 | -52% | 1 | 1 | 0% | 960 | 1,829 | +91% | 0 | 0 | — |
case-06 | fail→pass | 11,649 | 3,927 | -66% | 1 | 1 | 0% | 2,090 | 2,094 | +0% | 0 | 0 | — |
case-07 | fail→pass | 11,869 | 3,265 | -72% | 1 | 1 | 0% | 1,751 | 1,750 | -0% | 0 | 0 | — |
case-08 | fail→pass | 9,978 | 2,572 | -74% | 1 | 1 | 0% | 1,728 | 1,796 | +4% | 0 | 0 | — |
case-09 | fail→pass | 12,504 | 2,856 | -77% | 1 | 1 | 0% | 2,275 | 1,805 | -21% | 0 | 0 | — |
case-10 | fail→pass | 9,944 | 4,258 | -57% | 1 | 1 | 0% | 1,688 | 2,047 | +21% | 0 | 0 | — |
case-11 | fail→pass | 10,890 | 2,985 | -73% | 1 | 1 | 0% | 1,747 | 1,825 | +4% | 0 | 0 | — |
case-12 | fail→pass | 9,851 | 2,553 | -74% | 1 | 1 | 0% | 1,540 | 1,772 | +15% | 0 | 0 | — |
case-13 | fail→pass | 11,570 | 4,468 | -61% | 1 | 1 | 0% | 1,827 | 2,118 | +16% | 0 | 0 | — |
case-14 | fail→pass | 11,702 | 3,907 | -67% | 1 | 1 | 0% | 1,958 | 2,033 | +4% | 0 | 0 | — |
case-15 | pass→pass | 3,810 | 3,448 | -10% | 1 | 1 | 0% | 566 | 1,955 | +245% | 0 | 0 | — |
case-16 | fail→pass | 14,991 | 8,628 | -42% | 1 | 1 | 0% | 2,663 | 2,933 | +10% | 0 | 0 | — |
case-17 | fail→pass | 15,255 | 8,321 | -45% | 1 | 1 | 0% | 2,198 | 2,717 | +24% | 0 | 0 | — |
case-19 | fail→pass | 13,080 | 1,767 | -86% | 1 | 1 | 0% | 1,887 | 1,586 | -16% | 0 | 0 | — |
case-20 | fail→pass | 16,521 | 4,160 | -75% | 1 | 1 | 0% | 2,851 | 2,038 | -29% | 0 | 0 | — |
case-21 | pass→pass | 13,540 | 8,848 | -35% | 1 | 1 | 0% | 2,153 | 2,850 | +32% | 0 | 0 | — |
case-22 | fail→pass | 13,135 | 8,942 | -32% | 1 | 1 | 0% | 2,384 | 2,904 | +22% | 0 | 0 | — |
case-23 | pass→pass | 11,019 | 6,848 | -38% | 1 | 1 | 0% | 1,805 | 2,505 | +39% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 22 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +70 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.