# Tools Content Workflow

**Last Updated:** 2026-04-01

Master workflow for tools page content optimization. Parallel to [TEMPLATE_CONTENT_WORKFLOW.md](../../systems/templates/TEMPLATE_CONTENT_WORKFLOW.md) and [BLOG_POST_IMPROVEMENT_PROCESS.md](../../content/blog/BLOG_POST_IMPROVEMENT_PROCESS.md).

**Data-first baseline (any improvement sprint):** [PAGE_IMPROVEMENT_DATA_PLAYBOOK.md](../../content/PAGE_IMPROVEMENT_DATA_PLAYBOOK.md) — Phase 0 GSC/GA before locking outlines. **Step-by-step iteration** (period compare, Firecrawl, PR snippet): [PAGE_IMPROVEMENT_ITERATION_CHECKLIST.md](../../content/PAGE_IMPROVEMENT_ITERATION_CHECKLIST.md).

**Data collection inventory:** Script → output paths, credit notes, GSC template, slug matrix, and blog-parity gap: [DATA_COLLECTION_TOOLS.md](../../content/tools/DATA_COLLECTION_TOOLS.md) · [TOOLS_SLUG_MATRIX.md](../../content/tools/TOOLS_SLUG_MATRIX.md) · suggested follow-ups: [TOOLS_SEO_IMPROVEMENT_BACKLOG.md](../../content/tools/TOOLS_SEO_IMPROVEMENT_BACKLOG.md).

**Marketing pages (non-tool FAQs):** Same “one FAQPage / one data file” rule as tools, using `misc-faqs/` or `industry-faqs/` + [`render-faq-json.php`](../../v2/components/render-faq-json.php) + [`include-marketing-faq-jsonld.php`](../../v2/components/include-marketing-faq-jsonld.php). Hub: [FAQ_WEBSITE_STANDARD.md](../../content/FAQ_WEBSITE_STANDARD.md); verify `verify-faq-jsonld-parity.php --all-misc-faqs`, `audit-marketing-faq-ssot.php`.

## Overview

0. **Baseline analytics** – Refresh `tools-performance-gsc.json` / `tools-performance-ga4.json` (`collect-tools-performance-gsc.php`, `collect-tools-performance-ga4.php`; optional `collect-tools-performance-ga4.php --compare-28d` for rolling engagement PoP). For query-level diagnosis, run `collect-tool-gsc-queries.php --tool={slug}` or `--path=...` → `gsc-queries.json`; use `--start`/`--end` for fixed ranges; `compare-gsc-query-exports.php` for two-file diffs ([GSC_QUERY_EXPORT_SCHEMA.md](../../content/tools/GSC_QUERY_EXPORT_SCHEMA.md)).
0b. **Metrics synthesis (recommended)** – After step 0 (+ optional SISTRIX per-tool refresh), run `php v2/scripts/tools/generate-tool-data-synthesis.php --tool={slug} --output=docs/content/tools/{slug}/DATA_DRIVEN_SYNTHESIS.md` so Phase 2 outline/meta/FAQ decisions cite **committed JSON** in one file ([DATA_COLLECTION_TOOLS.md](../../content/tools/DATA_COLLECTION_TOOLS.md) § *Per-tool synthesis*).
1. **Data collection** – SISTRIX keywords, PAA, competitor analysis, competitive depth
2. **SERP & outline** – SERP skeleton, content outline; manual SERP review (~30 min)
3. **Validation** – validate-improvement-readiness, validate-content-completeness
4. **Content creation** – Edit PHP content blocks per outline (colored cards, tables, callouts). **Visible copy only:** Do not publish research or implementation meta (e.g. FAQ-JSON, strukturierte Daten, „typische Suchanfragen“, SERP-/Suchbegriff-Framing). Keep PAA/SERP maps and JSON–HTML parity notes in `docs/` and review; see `.cursor/rules/tools-pages-content-blocks.mdc` § Reader-facing copy.
4b. **Keyword→surface mapping (before ship)** – After drafts exist, map **primary and secondary** phrases from `docs/content/tools/{slug}/data/keywords-candidate.json` (and `DATA_DRIVEN_SYNTHESIS.md`) to **published surfaces** so demand data is not stranded in `docs/`. Use the copy-paste checklist: [`docs/content/tools/_templates/TOOL_KEYWORD_SURFACE_CHECKLIST.md`](../../content/tools/_templates/TOOL_KEYWORD_SURFACE_CHECKLIST.md). Integrate phrases **naturally** (German compounds, questions readers ask) — never frame visible copy as „Keywords“ or SERP tuning.

| Surface | What to align (examples) |
|--------|-------------------------|
| `<title>`, meta description, OG title/description | Primary head term + year + benefit + disclaimer tail |
| `WebPage` / `SoftwareApplication` / `HowTo` in `@graph` | Consistent naming with hero; no stuffing |
| Hero H1 + lead | Primary term early; secondary term once where it reads well |
| First SEO H2 + opening paragraph | Tool name + „online berechnen“ / inverted phrasing if volume-backed |
| `v2/data/tools_index_data.php` | Listing description + tags |
| `v2/data/tools-faqs/{slug}.json` | Question stems matching real user questions (AEO) |
| Optional check | `php v2/scripts/tools/audit-tool-keyword-coverage.php --tool={slug}` (dev signal only) |

5. **Post-write** – `audit-tools-content-blocks.py` (resolves `include __DIR__` tool partials), `validate-tool-content-completeness.php` (uses `v2/scripts/tools/tool-page-expand-includes.php` the same way); optional `php v2/scripts/tools/audit-tool-keyword-coverage.php --tool={slug}`
6. **Internal linking** – Run [NEW_TOOL_LINKING_CHECKLIST.md](../../content/tools/NEW_TOOL_LINKING_CHECKLIST.md)
7. **OG image + carousel** – Before publishing: add `og-image-specs.json`; for `--gemini-visuals` add **`VISUAL_DESCRIPTIONS` + `VISUAL_ONLY_PROMPTS`** for `{tool-slug}` in `generate-og-image-gemini.py` (required for hybrid Gemini); run `python3 v2/scripts/og-images/generate-og-images.py --type={tool-slug} --gemini-visuals --workers 1`; `validate-og-images.py` + `validate-og-logo.py`; wire `og-image-registry.php`. Include `tools_carousel.php` **before** FAQ; update `tools_index_data.php` and `$filenameToSlugMap` in `tools_carousel.php` if needed. Drift check: `make og-audit`. Copy-paste: [_templates/NEW_TOOL_PUBLICATION_TODO.md](../../content/_templates/NEW_TOOL_PUBLICATION_TODO.md). See [NEW_PAGE_OG_AND_SOCIAL_CHECKLIST.md](../../systems/og-images/NEW_PAGE_OG_AND_SOCIAL_CHECKLIST.md).

## Results report layout (interactive tools)

- **Reference UIs:** Dual KPI hero + centered metrics row — [`v2/pages/tools_stundenlohnrechner.php`](../../v2/pages/tools_stundenlohnrechner.php); large headline result + `h-4` progress + summary tiles — [`v2/pages/tools_arbeitstage_rechner.php`](../../v2/pages/tools_arbeitstage_rechner.php). Kurzarbeitergeld report: [`v2/includes/tools/kurzarbeitergeld-rechner/calculator-section.php`](../../v2/includes/tools/kurzarbeitergeld-rechner/calculator-section.php) + scoped CSS in [`v2/pages/tools_kurzarbeitergeld_rechner.php`](../../v2/pages/tools_kurzarbeitergeld_rechner.php).
- **Progressive disclosure:** Long **Eingaben** grids and **Rechenweg** lists → `<details>` / `<summary>` (keyboard focus ring). Avoid duplicating the same headline number in hero and a secondary tile.
- **Exports:** PDF/CSV layout for KUG is **data-driven** (`v2/js/kurzarbeitergeld/export.js`); on-page HTML refactors do not have to mirror the PDF DOM.

## Skyscraper-style content (high-intent tools)

After Phase 1–2 data exists, **outrank thin competitors** by design (not by stuffing):

1. **Map the SERP:** Use `competitor-analysis.json` headings + FAQ counts + `SERP_ANALYSIS.md` – cover every **distinct** angle (Definition, Rechner-Nutzung, Sätze/Jahr, Kappung, Arbeitsweg, Steuerwirkung, Abgrenzungen) in **one** strong section each; skip irrelevant H2s (Jobs, generische „Weitere Rechner“).
2. **Match PAA intent:** Align blocks and FAQ wording with `paa-questions.json` (high-traffic questions get visible answers + schema).
3. **Proof & utility:** Add **2–4 gerechnete Beispiele**, eine **Checkliste** (Steuererklärung / Eingaben), und **Abgrenzungen** (Dienstreise, Homeoffice) – genauer als ein 800-Wort-Klon.
4. **Internal links:** Register the slug in `docs/data/tools-internal-link-mapping.json`, dann `php v2/scripts/tools/audit-tools-internal-links.php` (bei Bedarf) – Lexikon **mit trailing slash**, Tools/Produkt **ohne** (siehe [CANONICAL_URLS_AND_LINKING.md](../../development/CANONICAL_URLS_AND_LINKING.md)).
5. **Refresh targets:** Wenn du bewusst unter „Max-Wortzahl“ eines Scrapings bleibst, **passe** `competitive-depth-analysis.md` **Target Word Count** an die redaktionelle Zielspanne an, damit `validate-tool-content-completeness.php` nicht Schein-Fails liefert.
6. **CONTENT_OUTLINE.md:** Nach `generate-tool-content-outline.php` die H2-Liste **redaktionell finalisieren** (Skyscraper-Themen, keine KK-Navigation). Der Generator filtert häufige Stör-Überschriften (Chat, Kontakt, „Mitglied werden“) per Blocklist in `generate-tool-content-outline.php` — trotzdem kurz gegen echte SERP-Winner prüfen.

## Quick Start

```bash
# Full pipeline
php v2/scripts/tools/run-tools-improvement-pipeline.php --tool=elterngeld-rechner

# Phase by phase
php v2/scripts/tools/collect-tool-keywords-sistrix.php --tool=elterngeld-rechner
php v2/scripts/tools/collect-tool-paa-questions.php --tool=elterngeld-rechner
php v2/scripts/tools/collect-tool-competitor-analysis.php --tool=elterngeld-rechner
php v2/scripts/tools/analyze-tool-competitor-depth.php --tool=elterngeld-rechner
php v2/scripts/tools/generate-tool-serp-skeleton.php --tool=elterngeld-rechner
php v2/scripts/tools/generate-tool-content-outline.php --tool=elterngeld-rechner
# Manual: Complete SERP_ANALYSIS.md (~30 min), edit CONTENT_OUTLINE.md
php v2/scripts/tools/validate-tool-improvement-readiness.php --tool=elterngeld-rechner
php v2/scripts/tools/validate-tool-content-completeness.php --tool=elterngeld-rechner
# Edit v2/pages/tools_{slug}.php content blocks
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner --format-check
php v2/scripts/tools/validate-tool-content-completeness.php --tool=elterngeld-rechner
```

## Data Directory Structure

```
docs/content/tools/{tool-slug}/
├── data/
│   ├── keywords-sistrix.json
│   ├── keywords-candidate.json
│   ├── paa-questions.json
│   ├── gsc-queries.json
│   ├── competitor-analysis.json
│   ├── competitive-depth-analysis.md
│   └── faq-research.json (optional)
├── DATA_DRIVEN_SYNTHESIS.md   ← optional but recommended; `generate-tool-data-synthesis.php`
├── SERP_ANALYSIS.md
└── CONTENT_OUTLINE.md
```

## PHP partials (optional maintainability)

For heavy editorial churn, you may split **below-the-fold** SEO + FAQ + JSON-LD **without** changing rendered HTML:

- **Includes:** `v2/includes/tools/{slug}/seo-content.php`, `faq-section.php`; structured data in `schema-graph.json`.
- **Markers:** Keep `<!-- SEO Content Sections -->` at the start of the SEO partial and `<!-- FAQ Section -->` at the start of the FAQ partial so `audit-tools-content-blocks.py` still extracts sections.
- **Head:** `json_decode` guard + `echo` trimmed JSON from `schema-graph.json` (see `v2/pages/tools_pendlerpauschale_rechner.php`).
- **Sync rule:** FAQ visible copy and `FAQPage` in `schema-graph.json` must stay **1:1** (same questions and answer text).

## Calculator form UX (card selections & alignment)

When refactoring tool forms (not only SEO blocks):

- **Card radios/checkboxes** for small enums (roughly 2–6 options) can improve scannability; the Mehrwertsteuer tool uses full card/segment patterns where space allows. **Kurzarbeitergeld-Rechner** (`v2/includes/tools/kurzarbeitergeld-rechner/calculator-section.php`) mixes **compact segments** (Steuerklasse), **select** (KV, Bundesland), **binary rows** (RV/ALV), and **switch rows** for independent booleans — see `.cursor/rules/tools-pages-core-design.mdc` § *Control density & selection mode*.
- **Selects** remain appropriate for long lists (e.g. all German states) and for medium-length enums when reducing form height (e.g. KV type).
- **Row alignment:** Use a fixed-min-height hint row under paired inputs so columns stay visually aligned when only one side has helper copy.
- **Independent vs exclusive:** If two controls are **not** mutually exclusive, say so in the legend (e.g. “zwei unabhängige Schalter”); use visible on/off (switch) so they are not mistaken for a single-choice card group.
- **Exports / logic:** Markup-only refactors must keep the same `x-model` / value strings so `getCalculationData()` and exports stay unchanged unless intentionally updated.
- **Rule detail:** `.cursor/rules/tools-pages-core-design.mdc` § *Card selection vs native select* and § *Control density & selection mode*.

## Calculator results, Rechenweg & export parity

- **On-page vs gated export:** For tools that gate PDF/CSV, still show the **main numeric story** on the page (e.g. Netto-Soll → Ist → Differenz → KUG) with a short **Rechenweg** so the headline number is verständlich; avoid duplicating an Arbeitstage-style blur for the same breakdown when exports are already gated.
- **Parity:** PDF/CSV **Kennzahlen** should match on-page headline metrics (e.g. Netto-Soll where the model uses BBG-gekapptes Soll-Brutto).
- **HubSpot / `collect-lead`:** Prefer **scalar** fields in `clean*` / `format*` (flags, percentages); omit full nested payroll snapshots from CRM text payloads.

### Results report layout (visual hierarchy)

- **Canonical export buttons (PDF + CSV):** Match [`v2/pages/tools_arbeitstage_rechner.php`](../../v2/pages/tools_arbeitstage_rechner.php) (result card, top-right): PDF = `bg-ordio-blue text-white rounded-md hover:bg-blue-700` + download SVG + `mr-2`; CSV = white/outline + `hover:text-gray-700` + sheet SVG + `mr-2`. Mobile tightening: same page’s `@media (max-width: 768px)` rules for `.result-card .absolute.top-4.right-4`. **Kurzarbeitergeld** mirrors this in [`v2/includes/tools/kurzarbeitergeld-rechner/calculator-section.php`](../../v2/includes/tools/kurzarbeitergeld-rechner/calculator-section.php) with scoped CSS under `.kug-results-section`.
- **Dual KPI hero:** Reference [`v2/pages/tools_stundenlohnrechner.php`](../../v2/pages/tools_stundenlohnrechner.php) (gradient headline cards). KUG combines **Kurzarbeitergeld** + **Summe Netto + KUG** in a two-column hero, then optional **coverage bar** (Netto-Differenz deckend), summary tiles, **Deine Angaben** strip, tinted **Rechenweg** panel, collapsible compare table, left-border **Hinweis**.
- **Scoped CSS:** Prefer page-scoped classes (e.g. `.kug-results-*` in `tools_kurzarbeitergeld_rechner.php`) over edits to [`v2/css/tools-pages.css`](../../v2/css/tools-pages.css) unless the pattern is promoted to many tools.
- **Exports (Kurzarbeitergeld):** [`v2/js/kurzarbeitergeld/export.js`](../../v2/js/kurzarbeitergeld/export.js) — CSV uses a single **DEINE ANGABEN** block (aligned with the on-page settings strip); PDF mirrors the report flow (**Kernaussage** → optional Deckung/BBG → **Deine Angaben** → **Kennzahlen** → Rechenweg → Einordnung → **Steuern und Sozialabgaben** Soll/Ist when `payrollSummary*` exist). After editing, run `npm run minify` so `export.min.js` stays in sync.

## FAQ JSON-LD (single source, `tools-faqs` tools)

For tools that use **`v2/data/tools-faqs/*.json`** with **`render-faq-json.php`**:

1. **One data file** drives the visible accordion and the FAQPage JSON-LD (no duplicate maintenance in `<head>`).
2. **After** `include '../base/footer.php'`, emit FAQ structured data with `ordio_echo_tools_faq_jsonld_script()` in `v2/helpers/faq-jsonld.php`, passing the **same** relative path as `$ordio_faq_json_relpath` and the page’s **canonical URL** (must match `<link rel="canonical">`; use `#faq` via the helper). The helper emits `@context: https://schema.org` on the script root (required so `FAQPage` is not resolved as a relative IRI); see [FAQ_WEBSITE_STANDARD.md](../../content/FAQ_WEBSITE_STANDARD.md) § FAQPage JSON-LD.
3. **Do not** embed a second `FAQPage` in a `<head>` `@graph` or a separate JSON-LD script for the same FAQ set (drift risk).
4. **Validation:** `php v2/scripts/tools/audit-tools-faq-schema-status.php` · `php v2/scripts/dev-helpers/verify-faq-jsonld-parity.php --all-tools` · `php v2/scripts/dev-helpers/audit-faq-jsonld-context.php`

### Google FAQ / structured data (internal notes, 2026)

- Treat **one coherent FAQPage** per URL; on-page FAQ text and `acceptedAnswer` (plain text via `faq_answer_html_to_schema_plain_text`) should stay aligned.
- **FAQ rich results** are not guaranteed for every site; ship consistent schema for AEO/helpfulness, not only for a rich badge.
- Never add fabricated ratings or review markup to FAQ schema.

**Out of scope here:** `tools_pendlerpauschale_rechner.php` (partials + `schema-graph.json`). `tools_shiftgpt.php` does not use the `tools-faqs` pattern.

## Content Block Styling Reference

Match Minijob/Arbeitslosengeld styling:

- **Section:** `bg-white`, `prose prose-lg max-w-none text-gray-600`
- **H2:** `font-gilroybold text-3xl sm:text-4xl leading-[102%] tracking-[-1.5px] text-[#333333] mb-8`
- **H3:** `font-inter600 text-xl`
- **Colored cards:** `bg-green-50`, `bg-orange-50`, `bg-blue-50`, `bg-purple-50`, `rounded-xl`, `border`
- **Example wrapper:** `bg-gray-50 p-6 rounded-xl mb-6`
- **FAQ:** `[&>summary::-webkit-details-marker]:hidden`, `font-inter600 text-lg`, chevron icon

Target: 800+ words, format variety (cards, tables, callouts).

## Audit Options

```bash
# Basic audit
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner

# With format check (colored cards, tables, callouts)
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner --format-check

# Auto-load keywords from data/keywords-sistrix.json when --keywords not provided
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner

# PAA coverage (auto-loads from data/paa-questions.json)
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner

# Outline comparison (auto-loads from CONTENT_OUTLINE.md)
python3 v2/scripts/tools/audit-tools-content-blocks.py elterngeld-rechner
```

## References

- [tools-pages-content-blocks.mdc](../../../.cursor/rules/tools-pages-content-blocks.mdc)
- [tools-pages-elterngeld-calculator.mdc](../../../.cursor/rules/tools-pages-elterngeld-calculator.mdc)
- [elterngeld-rechner-documentation.md](elterngeld-rechner-documentation.md)
- [TEMPLATE_CONTENT_WORKFLOW.md](../../systems/templates/TEMPLATE_CONTENT_WORKFLOW.md)
