# Internal Linking Workflow 2026

**Last Updated:** 2026-03-21

Comprehensive, integrated internal linking workflow for all content types (blog posts, content blocks, improvements).

**Key Rules:**
- **Lexikon 1:1:** When a term with a dedicated lexikon post is mentioned, link it at least once on first meaningful mention (mandatory).
- **Word-count targets:** Link count scales with content length (~1 per 250 words). Run `audit-internal-link-density.php` to validate.
- **No planned posts:** Only link to existing pages. Never link to planned or unpublished content.

## Overview

This workflow ensures internal linking is:
- **Proactive** - Integrated into content creation workflows, not an afterthought
- **Automated** - Uses scripts to suggest and validate links
- **Contextual** - Links are natural, grammatically correct, and add value
- **Comprehensive** - Covers all link types (lexikon, tools, industries, products, templates)

## Workflow Integration Points

### 1. New Blog Post Creation

**When:** After content draft, before final validation

**Steps:**

1. **Generate suggestions** (mandatory):
   ```bash
   php v2/scripts/blog/suggest-contextual-links.php --post={slug} --category={category}
   php v2/scripts/blog/suggest-ordio-feature.php --post={slug} --category={category}
   ```

2. **Review `data/suggested-contextual-links.json`**:
   - **Lexikon links (mandatory):** Add on first meaningful mention. Every mentioned term with a lexikon post must be linked at least once.
   - **Industry links:** Add when industry mentioned (1 link per industry)
   - **Tool links:** Add when calculable topic discussed (1-2 links max)
   - **Template/Download links:** Add when template or download topic mentioned
   - **Product links:** Add contextually per product mapping (1-2 links max)

3. **Apply links to content**:
   - Edit `content-draft.html` directly
   - Use natural anchor text (topic name, not generic phrases)
   - Link on first meaningful mention
   - Respect word boundaries (no partial-word links)

4. **Sync to JSON**:
   ```bash
   php v2/scripts/blog/update-post-content.php --post={slug} --category={category} --html=docs/content/blog/posts/{category}/{slug}/content-draft.html
   ```

5. **Validate** (before publishing):
   ```bash
   php v2/scripts/blog/audit-blog-lexikon-links.php --post={slug} --category={category} [--suggest-placements]
   php v2/scripts/blog/audit-blog-tool-links.php --post={slug} --category={category} [--suggest-placements]
   php v2/scripts/blog/audit-blog-industry-links.php --post={slug} --category={category}
   php v2/scripts/blog/audit-internal-link-density.php --post={slug} --category={category}
   php v2/scripts/blog/validate-new-post.php --post={slug} --category={category}
   ```

6. **When creating new lexikon post X:** Run `php v2/scripts/blog/suggest-bidirectional-links-for-new-post.php --post={slug} --category=lexikon` to find existing posts that mention X's topic and add in-content links to X.

**Checklist Integration:** See [NEW_POST_LINKING_CHECKLIST.md](NEW_POST_LINKING_CHECKLIST.md) step 9.

### 2. Content Improvement/Expansion

**When:** After content expansion, before final validation

**Steps:**

1. **Run suggestion scripts** (same as new posts):
   ```bash
   php v2/scripts/blog/suggest-contextual-links.php --post={slug} --category={category}
   ```

2. **Review existing links**:
   - Check for broken/redirected links
   - Improve anchor text if generic
   - Remove redundant links

3. **Add missing links**:
   - Review `suggested-contextual-links.json`
   - Add lexikon/industry/tool links where topics naturally appear
   - Use `--suggest-placements` flag for context suggestions

4. **Validate**:
   ```bash
   php v2/scripts/blog/audit-blog-lexikon-links.php --post={slug} --category={category}
   php v2/scripts/blog/validate-new-post.php --post={slug} --category={category}
   ```

### 3. Content Block Creation (Templates)

**When:** After content block draft, before validation

**When creating a new template** (before or with content blocks):

1. **Add to blog-template-mapping.json** templates section (topic keywords → `/vorlagen/{slug}`)
2. **Run audit** to find blog posts missing the template link:
   ```bash
   php v2/scripts/blog/audit-blog-template-links.php --suggest-placements
   ```
3. **Review** `docs/data/blog-template-links-audit.json` and add links to relevant blog posts

**Checklist:** [NEW_TEMPLATE_LINKING_CHECKLIST.md](../../systems/templates/NEW_TEMPLATE_LINKING_CHECKLIST.md)

**Content block steps:**

1. **Generate suggestions**:
   ```bash
   php v2/scripts/templates/suggest-template-contextual-links.php --template={id}
   ```

2. **Review suggestions**:
   - Add lexikon links when topics mentioned
   - Add tool links for calculable topics
   - Add industry links when industries mentioned

3. **Apply to content blocks**:
   - Edit `content/content.md`
   - Use natural anchor text
   - Link on first meaningful mention

4. **Validate**:
   ```bash
   php v2/scripts/templates/validate-template-internal-links.php --template={id}
   ```

### 4. Tools Internal Linking

**When:** After content blocks/FAQs creation, before publish (when creating a new tool)

**Steps:**

1. **Add tool to tools-internal-link-mapping.json** (lexikon, templates, product, related_tools)
2. **Add tool to blog-tool-mapping.json** (topic keywords → tool URL)
3. **Run audit** to find blog posts missing the tool link:
   ```bash
   php v2/scripts/blog/audit-blog-tool-links.php --suggest-placements
   ```
4. **Add min 2-3 internal links** in content blocks and FAQs (related tools, lexikon, templates, product)
5. **Run audit**:
   ```bash
   php v2/scripts/tools/audit-tools-internal-links.php [--tool=slug]
   ```
6. **Review** `docs/data/tools-internal-links-audit.json` and `docs/data/blog-tool-links-audit.json` for gaps

**Checklist:** [NEW_TOOL_LINKING_CHECKLIST.md](../tools/NEW_TOOL_LINKING_CHECKLIST.md)

See [TEMPLATES_TOOLS_DOWNLOADS_INTERNAL_LINKING.md](../../systems/internal-linking/TEMPLATES_TOOLS_DOWNLOADS_INTERNAL_LINKING.md).

### 5. Download Internal Linking

**When:** After download page creation, before publish (when creating a new download)

**Steps:**

1. **Add download to download-internal-link-targets.json**
2. **Add download to blog-template-mapping.json** downloads section (topic keywords → download URL)
3. **Run audit** to find blog posts missing the download link:
   ```bash
   php v2/scripts/blog/audit-blog-download-links.php --suggest-placements
   ```
4. **Add min 2 internal links** in hero, description, or FAQ answers (lexikon, tools, templates, product)
5. **Run audit**:
   ```bash
   php v2/scripts/audit-download-internal-links.php [--download=slug]
   ```
6. **Review** `docs/data/download-internal-links-audit.json` and `docs/data/blog-download-links-audit.json` for gaps

**Checklist:** [NEW_DOWNLOAD_LINKING_CHECKLIST.md](../pages/download-pages/NEW_DOWNLOAD_LINKING_CHECKLIST.md)

See [TEMPLATES_TOOLS_DOWNLOADS_INTERNAL_LINKING.md](../../systems/internal-linking/TEMPLATES_TOOLS_DOWNLOADS_INTERNAL_LINKING.md).

## Link Type Guidelines

### Lexikon-to-Lexikon Links

**When to add:**
- Topic mentioned that has dedicated lexikon post
- First meaningful mention (not forced)

**How to add:**
- Use natural anchor text (topic name)
- Check `docs/content/blog/lexikon-inventory/LEXIKON_INVENTORY_REPORT.md` for available posts
- Link where topic appears naturally in content

**Example:**
```html
✅ "Ein Talent Acquisition Manager benötigt <a href="/insights/lexikon/soft-skills/">Soft Skills</a> wie Kommunikation."
❌ "Mehr zu Soft Skills findest du im Lexikon." (forced phrase)
```

### Tool Links

**When to add:**
- Content discusses calculable topic (Midijob, TVöD, Zuschläge, etc.)
- 1-2 links max per post
- Check `docs/data/blog-tool-mapping.json` for mappings

**How to add:**
- Use natural anchor text (e.g., "kostenlosen Midijob-Rechner")
- Place in calculation examples or how-to sections

**Example:**
```html
✅ "Berechne deinen Midijob mit unserem <a href="/tools/midijob-rechner/">kostenlosen Midijob-Rechner</a>."
```

### Industry Links

**When to add:**
- Content mentions specific industry (Einzelhandel, Gastronomie, etc.)
- 1 link per industry mentioned
- Check `docs/data/blog-industry-mapping.json` for mappings

**How to add:**
- Use industry name as anchor text
- Link where industry naturally appears

**Example:**
```html
✅ "Besonders in Branchen mit Schichtbetrieb wie <a href="/branchen/gastronomie">Gastronomie</a> oder <a href="/branchen/gesundheitswesen">Pflege</a>."
```

### Product Links

**When to add:**
- Content discusses solution/problem that matches Ordio feature
- 1-2 links max per post
- Match feature to content topic (see `ordio-promotion-contextual.mdc`)

**How to add:**
- Use descriptive anchor text (e.g., "Schichtplanung mit Ordio")
- Place in solution sections or CTAs

**Example:**
```html
✅ "Für die digitale <a href="/schichtplan">Schichtplanung</a> kannst du Ordio nutzen."
```

## Quality Standards

### Anchor Text Requirements

- ✅ **Natural:** Fits grammatically into sentence
- ✅ **Descriptive:** Keyword-rich, not generic
- ✅ **Varied:** Don't repeat same anchor text >3 times
- ✅ **Contextual:** Matches surrounding content

### Placement Requirements

- ✅ **First meaningful mention** (not forced)
- ✅ **Not right after section titles**
- ✅ **Not at end of paragraph** (unless conclusion/CTA)
- ✅ **Minimum 200 characters** between links (avoid link dumps)

### Word Boundary Requirements (German)

- ✅ Link complete words only
- ❌ Don't link "Checkliste" inside "Checklisten" (plural)
- ❌ Don't link "Schichtplanungs" inside "Schichtplanungsfunktionen" (compound)

**Technical:** All scripts use German-aware word boundary matching.

## Natural linking vs. meta narration

- **Goal:** Readers see *why* a related page matters from the sentence around the link — not a statement about search strategy or “our” linking policy.
- **Avoid in body copy:** Framing links as editorial operations (“wir verlinken”, “verweisen wir gezielt”, “für Suchintention und interne Verlinkung”), or explaining that a separate URL exists to capture a query. Differentiate sibling articles in plain language (“Der Überblick …; hier geht es um …”).
- **Automation:** `python3 v2/scripts/blog/audit-meta-intro-language.py` (or `make audit-blog-meta-intros`) flags common patterns in `docs/content/blog/posts/**/content.html` for manual rewrite. See [PEOPLE_FIRST_INTRO_AND_LINKING.md](PEOPLE_FIRST_INTRO_AND_LINKING.md).

## Automation Scripts

### Suggestion Scripts

| Script | Purpose | Output |
|--------|---------|--------|
| `suggest-contextual-links.php` | Per-post tool/industry/lexikon suggestions | `data/suggested-contextual-links.json` |
| `suggest-ordio-feature.php` | Product + tool + industry suggestions | Console output |
| `suggest-template-contextual-links.php` | Template content block suggestions | Template data file |

### Audit Scripts

| Script | Purpose | Flags |
|--------|---------|-------|
| `audit-blog-lexikon-links.php` | Find missing lexikon links | `--suggest-placements` |
| `audit-blog-tool-links.php` | Find missing tool links | `--suggest-placements` |
| `audit-blog-template-links.php` | Find missing template links | `--suggest-placements` |
| `audit-blog-download-links.php` | Find missing download links | `--suggest-placements` |
| `audit-blog-industry-links.php` | Find missing industry links | - |
| `validate-template-internal-links.php` | Validate template links (min 3) | `--suggest-placements` |
| `audit-tools-internal-links.php` | Audit tools links (min 2) | `--tool=slug` |
| `audit-download-internal-links.php` | Audit download links (min 2) | `--download=slug` |

### Helper Scripts

| Script | Purpose | Usage |
|--------|---------|-------|
| `find-content-mentioning-topic.php` | Find content (blog, tools, templates, downloads) that mentions a topic | `php v2/scripts/internal-linking/find-content-mentioning-topic.php --topic=X` – use when adding cross-resource links for new tools/templates/downloads |

### Bulk Operations

| Script | Purpose | Usage |
|--------|---------|-------|
| `suggest-contextual-links.php --all` | Generate suggestions for all posts | Pre-audit step |
| `add-contextual-links-from-suggestions.php --all` | Apply suggestions in bulk | After review |

## Quick Reference Checklist

### For New Posts

- [ ] Run `suggest-contextual-links.php` after content draft
- [ ] Review `suggested-contextual-links.json`
- [ ] **Check for duplicate links** (same URL appearing multiple times)
- [ ] Add lexikon links on first meaningful mention
- [ ] Add industry links when industries mentioned (1 per industry)
- [ ] Add tool links for calculable topics (1-2 max)
- [ ] Add product links contextually (1-2 max per feature)
- [ ] **Reduce product link repetition** (max 1-2 per product feature)
- [ ] Run audit scripts before publishing (optional: `make audit-blog-meta-intros` for meta-intro phrasing)
- [ ] Fix any validation failures
- [ ] **Verify link distribution** (10-15 total links, distributed throughout content)

### For Content Improvements

- [ ] Run `suggest-contextual-links.php` after expansion
- [ ] Review existing links (remove broken, improve generic)
- [ ] Add missing links from suggestions
- [ ] Validate with audit scripts

### For Content Blocks

- [ ] Run `suggest-template-contextual-links.php` after draft
- [ ] Add links to content blocks
- [ ] Validate with `validate-template-internal-links.php`

## Common Mistakes to Avoid

1. **Duplicate links:**
   - ❌ Same URL appearing multiple times (e.g., Fachkräftemangel linked twice)
   - ✅ Check for existing links before adding new ones

2. **Product link repetition:**
   - ❌ Same product link appearing 3+ times
   - ✅ Limit product links to 1-2 per feature per post

3. **Forced link phrases:**
   - ❌ "Mehr dazu im Lexikon X"
   - ✅ Link term where it appears naturally

4. **Generic anchor text:**
   - ❌ "mehr zu dienstplan"
   - ✅ "Dienstplan erstellen"

5. **Link dumps:**
   - ❌ List of links at end of paragraph
   - ✅ Integrate links naturally in content flow

6. **Partial-word links:**
   - ❌ Linking "Checkliste" inside "Checklisten"
   - ✅ Link complete words only

7. **Over-linking:**
   - ❌ 5+ links in one paragraph
   - ✅ Maximum 1-2 links per paragraph

## Related Documentation

- [INTERNAL_LINKING_GUIDE.md](guides/INTERNAL_LINKING_GUIDE.md) - Complete guide with examples
- [NEW_POST_LINKING_CHECKLIST.md](NEW_POST_LINKING_CHECKLIST.md) - New post checklist
- [INTERNAL_LINKING_PROCESS.md](INTERNAL_LINKING_PROCESS.md) - Process overview
- [blog-tool-linking.mdc](../../.cursor/rules/blog-tool-linking.mdc) - Tool linking rules
- [ordio-promotion-contextual.mdc](../../.cursor/rules/ordio-promotion-contextual.mdc) - Product linking rules

## Workflow Integration Summary

**New Posts:** Linking happens after content draft, before validation (step 9 in NEW_POST_LINKING_CHECKLIST.md)

**Content Improvements:** Linking happens after expansion, before final validation

**Content Blocks:** Linking happens after draft, before template validation

**All workflows:** Use suggestion scripts → Review → Apply → Validate
