Skip to content
Content
Skill

/blog-taxonomy

Extract, suggest, and sync tags and categories for blog posts across all major CMS platforms. Supports WordPress REST API, Shopify GraphQL, Ghost Content API, Strapi REST/GraphQL, and Sanity GROQ. Generates tag suggestions from content analysis (keyword frequency, heading

From plugin
claude-blog
1.6k32 skills20 agents
Install
$ npx -y skills add AgriciDaniel/claude-blog --skill blog-taxonomy --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/blog-taxonomy

Context preview

The summary Claude sees to decide when to auto-load this skill.

Extract, suggest, and sync tags and categories for blog posts across all major CMS platforms. Supports WordPress REST API, Shopify GraphQL, Ghost Content API, Strapi REST/GraphQL, and Sanity GROQ. Generates tag suggestions from content analysis (keyword frequency, heading

SKILL.md

blog-taxonomy.SKILL.md
name: blog-taxonomy
description: >
  Extract, suggest, and sync tags and categories for blog posts across all major
  CMS platforms. Supports WordPress REST API, Shopify GraphQL, Ghost Content API,
  Strapi REST/GraphQL, and Sanity GROQ. Generates tag suggestions from content
  analysis (keyword frequency, heading extraction, semantic grouping), enforces
  minimum post-count thresholds to prevent thin tag archives, and syncs taxonomy
  via authenticated API calls. Use when user says "tags", "categories", "taxonomy",
  "tag suggestions", "sync tags", "WordPress tags", "Shopify tags".
user-invokable: true
argument-hint: "[suggest|sync|audit] [file-or-cms]"
license: MIT

Blog Taxonomy

Manage tags, categories, and topic clusters across CMS platforms.

Commands

| Command | Purpose | |---------|---------| | `/blog taxonomy suggest <file>` | Extract candidate tags and categories from content | | `/blog taxonomy sync <cms>` | Push taxonomy to CMS via authenticated API | | `/blog taxonomy audit [directory]` | Check for thin tags, orphan tags, taxonomy bloat |

Tag Suggestion Workflow

Step 1: Parse Content Structure

Read the target file and extract:

  • All H2 and H3 headings (primary topic signals)
  • Bold and italic phrases (emphasis signals)
  • Existing frontmatter tags/categories if present

Step 2: Frequency Analysis

Scan the body text for high-frequency phrases:

  • 1-word terms: minimum 4 occurrences (excluding stop words)
  • 2-word phrases: minimum 3 occurrences
  • 3-word phrases: minimum 2 occurrences

Exclude common non-tag words: articles, prepositions, conjunctions, pronouns.

Step 3: Semantic Grouping

Group related candidates into clusters:

  • Merge singular/plural variants (keep the more common form)
  • Merge hyphenated and non-hyphenated forms
  • Group synonyms under the highest-frequency term

Step 4: Deduplicate and Rank

  • Fuzzy match on slugified names (Levenshtein distance <= 2)
  • Do not auto-merge short slugs under 5 characters using Levenshtein alone; require token overlap or manual review
  • Score each candidate: `(frequency * 2) + (heading_presence * 5) + (emphasis * 1)`
  • Return top 5-10 ranked suggestions

Output Format

## Tag Suggestions: [Post Title]

| Rank | Tag | Score | Source |
|------|-----|-------|--------|
| 1 | content-marketing | 18 | H2 + 6 mentions |
| 2 | seo-strategy | 14 | H3 + 4 mentions |
| 3 | keyword-research | 11 | 5 mentions + bold |

### Suggested Categories
- Primary: [best-fit category]
- Secondary: [optional second category]

CMS Adapters

Adapter Overview

| CMS | API Type | Auth Method | Tags Model | |-----|----------|-------------|------------| | WordPress | REST | Application Passwords (base64) | First-class entities with IDs | | Shopify | GraphQL (Admin API) | Admin API access token | String array on Article | | Ghost | REST (Admin API) | API key with JWT signing | First-class entities | | Strapi | REST or GraphQL | API token (Bearer) | User-defined content type | | Sanity | GROQ / Mutations | Project token (Bearer) | Document type |

WordPress Adapter

**List tags**:

GET {CMS_URL}/wp-json/wp/v2/tags?per_page=100&search={keyword}
Authorization: Basic {base64(username:app_password)}

**Create tag**:

POST {CMS_URL}/wp-json/wp/v2/tags
Body: {"name": "Tag Name", "slug": "tag-name", "description": "Optional"}

**List categories** (hierarchical, supports parent field):

GET {CMS_URL}/wp-json/wp/v2/categories?per_page=100

**Create category**:

POST {CMS_URL}/wp-json/wp/v2/categories
Body: {"name": "Category", "slug": "category", "parent": 0}

**Assign tags to post**:

POST {CMS_URL}/wp-json/wp/v2/posts/{id}
Body: {"tags": [1, 2, 3], "categories": [4]}

Pagination: follow `X-WP-TotalPages` header for full listing.

Shopify Adapter

Tags on Shopify are string arrays on the Article object, not first-class entities.

**Update article tags** (GraphQL Admin API):

mutation {
  articleUpdate(id: "gid://shopify/Article/123", article: {
    tags: ["tag-one", "tag-two", "tag-three"]
  }) {
    article { id tags }
    userErrors { field message }
  }
}

**List all tags in use** (GraphQL):

{
  articles(first: 250, after: $cursor) {
    pageInfo { hasNextPage endCursor }
    edges {
      node { id title tags }
    }
  }
}

Auth header: `X-Shopify-Access-Token: {token}`

Pagination: loop while `pageInfo.hasNextPage` is true, passing `endCursor` as the next `$cursor`.

Note: REST API marked legacy Oct 2024. GraphQL required for new apps since Apr 2025.

Ghost Adapter

**List tags**:

GET {CMS_URL}/ghost/api/admin/tags/?limit=all
Authorization: Ghost {jwt_token}

**Create tag**:

POST {CMS_URL}/ghost/api/admin/tags/
Body: {"tags": [{"name": "Tag Name", "slug": "tag-name"}]}

JWT generation: sign with admin API key (id:secret format), iat = now, exp = 5 min, audience = `/admin/`.

Strapi Adapter

Endpoint auto-generated from content types. Typical setup:

GET {CMS_URL}/api/tags?pagination[pageSize]=100
POST {CMS_URL}/api/tags
Body: {"data": {"name": "Tag Name", "slug": "tag-name"}}
Authorization: Bearer {api_token}

Pagination: increment `pagination[page]` until all pages are exhausted.

Strapi v4 responses use the `data` wrapper with `attributes`; Strapi v5 uses a flatter response shape. Detect the version or normalize both shapes before deduplication. Check your content type schema for field names.

Sanity Adapter

**Query tags** (GROQ):

*[_type == "tag"] { _id, name, slug }

**Create tag** (Mutations API):

POST https://{project_id}.api.sanity.io/{SANITY_API_VERSION}/data/mutate/{dataset}
Body: {"mutations": [{"create": {"_type": "tag", "name": "Tag", "slug": {"current": "tag"}}}]}
Authorization: Bearer {token}

Default `SANITY_API_VERSION` to a current tested API date supplied by the project environment; do not hard-code it in generated requests.

Taxonomy Audit Workflow

Step 1: Inven

Read more
Ships withclaude-blog

claude-blog is a Claude Code skill suite that writes, optimizes, audits, localizes, and refreshes blog content at scale. Every article is evaluated for Google-aligned usefulness and internal AI citation readiness heuristics.

Get the whole plugin

Other skills on claude-blog.