| name | tools-page-seo-optimizer |
| description | Framework-agnostic SEO workflow for any site with multiple tool, product, or feature pages. Covers duplicate content, unique meta tags, heading hierarchy, internal linking, URL slugs, E-E-A-T, content registry pattern for scaling 50–500 pages, and blog content strategy for position 50–68 keywords. |
| category | seo |
| risk | safe |
| source | community |
| source_type | community |
| author | whoisabhishekadhikari |
| date_added | 2026-06-19 |
| tags | ["seo","tools-pages","product-pages","duplicate-content","content-registry","meta-tags","internal-linking","url-slugs","e-e-a-t","framework-agnostic"] |
| tools | ["claude-code","cursor","codex-cli","gemini-cli","opencode"] |
| version | 1.0.0 |
Tools Page SEO Optimizer
You are an expert in technical SEO and content strategy for sites with large collections of tool, product, or feature pages. Your workflow is framework-agnostic — applies to Django, Rails, Laravel, Express, Next.js, Nuxt, Astro, WordPress, and static HTML.
Derived from a real audit that found 93 of 105 tool pages sharing identical template prose and ranking at average position 68. This skill is the playbook that fixes it.
Quick-Start Decision Tree
Full audit from scratch? → Run all phases in order
All tool pages rank the same? → Phase 2 (Content Registry) first
Meta titles/descriptions all generic? → Phase 1 (Meta Tags)
Tool pages buried / hard to navigate? → Phase 5 (Internal Linking)
Bad URL slugs? → Phase 6 (URL Slug Hygiene)
Site looks authorless to Google? → Phase 7 (E-E-A-T)
Stuck at position 50–68 on keywords? → Phase 9 (Blog Content Strategy)
Fixes deployed but unsure they're live? → Phase 10 (Live Verification)
Phase 0 — Codebase Reconnaissance
Before writing any code, locate these in the codebase. Names vary by framework — adapt.
| What to find | Common locations |
|---|
| URL routing | routes.rb, urls.py, routes/, pages/, app/ |
| Head / meta template | _head.html, layout.js, base.html, app.blade.php |
| Tool/page registry | config file, database seed, JSON, lib/guides.js, data/tools.js |
Answer these before writing a single line:
- How are tool pages generated — static files, database loop, config registry, CMS?
- Where is the shared template that renders
<title>, <meta name="description">, <h1>?
- Does each tool have its own content fields, or does every tool fall back to the same template prose?
- Is there a central list of all tool slugs you can iterate over programmatically?
Phase 1 — Meta Titles & Descriptions
The core problem
Every tool page sharing the same <title> template with only the tool name swapped in
is the single most common reason tool sites rank poorly. Google treats near-identical titles
as duplicate pages and demotes all of them.
Title tag formula
{Tool Name} | {Specific Outcome} — {Brand}
| ✅ Good | ❌ Bad |
|---|
Meta Tag Generator | Create Perfect SEO Titles Free — MySite | Meta Tag Generator - MySite Tools |
Broken Link Finder | Scan Any Page for Dead URLs — MySite | Broken Link Finder - Free Online Tool | MySite |
Rules:
- ≤ 60 characters total
- Primary keyword in the first 40 characters
- Every tool has a unique title — no two tools share the same one
- Include "Free" where accurate — measurably improves CTR
Meta description formula
{What it does — one action sentence}. {Key differentiator}. {CTA}.
Example: Scan any webpage for broken links in seconds. Checks internal and external URLs, exports results as CSV. Free, no account needed.
Rules:
- 120–160 characters
- Action verbs: Generate, Scan, Check, Analyze, Convert, Build, Find
- Every tool gets a custom description — zero template filler
Implementation (any framework)
<title>{{ tool.meta_title | default(tool.name + " | " + site_name) }}</title>
<meta name="description" content="{{ tool.meta_description | default(tool.tagline) }}">
Validation script — run before every deploy
import json, sys
tools = json.load(open('data/tools.json'))
errors = []
for t in tools:
slug = t.get('slug', '?')
title = t.get('meta_title', '')
desc = t.get('meta_description', '')
if not title: errors.append(f"MISSING TITLE: {slug}")
elif len(title) > 60: errors.append(f"TITLE TOO LONG ({len(title)}): {slug}")
if not desc: errors.append(f"MISSING DESC: {slug}")
elif len(desc) < 120: errors.append(f"DESC TOO SHORT ({len(desc)}): {slug}")
elif len(desc) > 160: errors.append(f"DESC TOO LONG ({len(desc)}): {slug}")
if errors:
print('\n'.join(errors)); sys.exit(1)
print(f"✅ All {len(tools)} tools passed meta validation")
Phase 2 — Content Registry (The Highest-Leverage Fix)
Root cause of poor rankings on tool sites: 80–95% of tool pages share identical
template prose. Google sees them as thin, near-duplicate pages and ranks none well.
Fix this before anything else.
Diagnosis
D1=$(grep -rn "powerful tool that helps" templates/ src/ 2>/dev/null | head -5)
[ -n "$D1" ] && echo " ✗ Shared template prose found" || echo " ✓ No shared prose"
D2=$(grep -rn "easy to use" templates/ src/ 2>/dev/null | head -5)
[ -n "$D2" ] && echo " ✗ Template filler found"
Registry entry structure (framework-agnostic)
slug: meta-tag-generator
name: Meta Tag Generator
meta_title: "Meta Tag Generator | Create Perfect SEO Titles & Descriptions Free"
meta_description: "Generate optimized title tags and meta descriptions with live character
counters. Enforces Google's 60/160 char limits. Instant, free, no account needed."
introduction: >
The meta tag generator creates the two most critical on-page SEO elements —
your title tag and meta description — with live character counters that enforce
Google's recommended limits before you publish. [80+ unique words minimum]
best_practices:
- "Include your primary keyword within the first 40 characters of the title"
- "Write a unique description per page — duplicate descriptions waste crawl budget"
- "Use action verbs in descriptions: Generate, Find, Check, Analyze"
how_to_steps:
- name: "Enter your page details"
text: "Type your target keyword, page topic, and a brief summary of the content"
- name: "Check the live character counters"
text: "Keep title ≤60 chars and description ≤160 chars"
- name: "Copy and paste the output"
text: "Paste the generated tags into your HTML <head> section"
faqs:
- q: "Does Google always use my meta description?"
a: "No — Google rewrites descriptions ~63% of the time. Write them anyway for
social shares and some SERPs."
- q: "What happens if my title is over 60 characters?"
a: "Google truncates it with an ellipsis, cutting off your message mid-sentence."
related_tools:
- og-tag-generator
- schema-markup-generator
- heading-analyzer
Minimum viable unique content per tool
| Field | Minimum | Priority |
|---|
meta_title | Unique, ≤60 chars | 🔴 Critical |
meta_description | Unique, 120–160 chars | 🔴 Critical |
introduction | 80+ unique words | 🔴 Critical |
best_practices | 3–5 tool-specific items | 🟡 High |
how_to_steps | 3 real steps for THIS tool | 🟡 High |
faqs | 2 tool-specific Q&As | 🟡 High |
related_tools | 2–4 slug references | 🟢 Medium |
Rule: complete one tool fully before starting the next.
Phase 3 — H1 and Heading Hierarchy
H1 formula
{Tool Name} | {Outcome Phrase}
Rules:
- One
<h1> per page — only the tool name/title
- Must be unique per page
Heading hierarchy
h1 — Tool name (one per page)
h2 — Major sections: "How It Works", "Best Practices", "FAQs", "Related Tools"
h3 — Subsections: individual FAQ items, feature callouts, step headers
Never skip levels. No h1 → h3 without an h2.
curl -s "https://yourdomain.com/tools/meta-tag-generator" \
| grep -oE '<h[1-6][^>]*>.*?</h[1-6]>'
Phase 4 — Accessibility
Accessibility failures lower Core Web Vitals scores — a direct ranking signal.
Every icon-only interactive element needs aria-label:
<button aria-label="Copy to clipboard"><svg>...</svg></button>
<button aria-label="Go to next page">›</button>
<input type="search" aria-label="Search tools" placeholder="Search...">
B=$(grep -rn "<button" templates/ 2>/dev/null | grep -v "aria-label" | grep -v ">[A-Za-z]" | head -5)
[ -n "$B" ] && echo " ⚠ Icon buttons missing aria-label:" && echo "$B" || echo " ✓ Buttons have aria-labels"
Phase 5 — Internal Linking
Internal links between tools are how PageRank flows through your site. A tool with no
inbound internal links is effectively invisible to Google even with great content.
Hub-and-Spoke model
Homepage
└── Category: Keyword Tools
├── Keyword Density Checker ←→ Keyword Suggestion Tool
└── SERP Preview Tool ←→ Meta Tag Generator
└── Category: Technical SEO
├── XML Sitemap Visualizer ←→ Robots.txt Creator
└── Robots.txt Creator ←→ Redirect Generator
Rules
- Every tool links to at least 2 related tools (use
related_tools from registry)
- Every tool is linked from at least 2 other tools or category pages
- No orphan tools — every tool reachable within 3 clicks from homepage
for slug in $(cat data/slugs.txt 2>/dev/null); do
C=$(grep -rl "$slug" templates/ 2>/dev/null | wc -l | tr -d ' ')
[ "$C" -lt 2 ] && echo " ORPHAN RISK: $slug ($C refs)"
done
Template implementation
{% if tool.related_tools %}
<section>
<h2>Related Tools</h2>
{% for slug in tool.related_tools %}
{% set rel = get_tool(slug) %}
<a href="/tools/{{ slug }}">{{ rel.name }} — {{ rel.tagline }}</a>
{% endfor %}
</section>
{% endif %}
Phase 6 — URL Slug Hygiene
| ✅ Good | ❌ Bad | Problem |
|---|
/tools/meta-tag-generator | /tools/tool-1 | No keywords |
/tools/keyword-density-checker | /tools/free-online-keyword-density-checker-tool-free | Keyword stuffed |
/tools/broken-link-finder | /tools/brokenLinkFinder | camelCase |
Formula: {primary-keyword-phrase} — lowercase, hyphens, no stop words, no "free" / "online" / "tool" padding.
curl -s "https://yourdomain.com/sitemap.xml" \
| grep -oE '<loc>[^<]+' | sed 's/<loc>//' \
| grep "/tools/" \
| awk -F'/tools/' '{print length($2), $2}' | sort -n | tail -20
If renaming a slug, always 301 redirect old → new and update all internal links.
Phase 7 — E-E-A-T Signals
Tool sites rank poorly when they look authorless and dateless.
Author byline + date (every tool page)
<p class="tool-byline">
Built by <a href="/about">Your Name</a>
<time datetime="{{ tool.updated_at }}"> · Updated {{ tool.updated_at | date }}</time>
</p>
Trust pillars section
<section class="trust-pillars">
<div>✅ <strong>100% Free</strong> — no account, no credit card</div>
<div>🔒 <strong>Privacy First</strong> — your data never leaves your browser</div>
<div>⚡ <strong>Instant Results</strong> — processed in under 1 second</div>
</section>
About / author page
Create /about with: real name, credentials, why you built the tools, contact info.
Link to it from every tool page byline. This is the single highest-impact E-E-A-T fix
for solo-built tool sites.
Phase 8 — Scaling to 100+ Tools
When the content registry pattern is working for 10–20 tools, the next challenge is
scaling it to 100+ without losing quality or introducing duplicates.
Batch completion gate
Never commit a partial batch. Before every commit touching tool content:
python3 -c "
import json
tools = json.load(open('data/tools.json'))
total = len(tools)
done = sum(1 for t in tools if t.get('introduction','').strip())
print(f'{done}/{total} tools have introduction content')
if done < total:
missing = [t['slug'] for t in tools if not t.get('introduction','').strip()]
print('Missing:', missing)
"
Only commit when the count is 100% complete. A partial batch (e.g. 93/105) means
12 tools still have thin template prose — enough for Google to flag the site as inconsistent.
Batch writing order
Prioritise tools in this order:
- Tools already receiving impressions in Google Search Console (low-hanging fruit)
- Tools in your most-linked categories (PageRank concentration)
- Remaining tools alphabetically
Build verification before commit
npm run build
python manage.py check
rails assets:precompile
Phase 9 — Blog Content Strategy (Position 50–68 Keywords)
Tool pages rank well for transactional keywords ("meta tag generator", "check broken links").