# Canonical URLs and Internal Linking

**Last Updated:** 2026-04-02

## Rule: Use main/canonical URLs only

**All internal links (PHP, HTML, JSON, templates) must point to the canonical (final) URL of the target page. Never use a URL that is defined in `.htaccess` as a redirect.**

### Do not link internally to `/kostenlos-testen`

`/kostenlos-testen` is a **paid campaign landing page** (`noindex`). Use **`/demo-vereinbaren`** (or `/preise` where appropriate) for editorial CTAs and FAQ links. **Do not change** post-submit redirects: paid LP and related forms still land users on **`/kostenlos-testen/danke`** (`typ.php`) after email/demo flows. See `.cursor/rules/no-internal-kostenlos-testen-links.mdc`.

## Trailing Slash Rules

**Different page types have different trailing slash requirements. Always use the correct pattern to avoid redirects:**

### Blog Posts (lexikon, ratgeber, inside-ordio)
- **Always use trailing slash**
- Examples:
  - `/insights/lexikon/homeoffice/` ✓
  - `/insights/ratgeber/gastronomie-mindestlohn/` ✓
  - `/insights/lexikon/homeoffice` ✗ (missing trailing slash)

### Product Pages
- **No trailing slash**
- Examples:
  - `/arbeitszeiterfassung` ✓
  - `/schichtplan` ✓
  - `/dokumentenmanagement` ✓
  - `/arbeitszeiterfassung/` ✗ (extra trailing slash)
- **Schichtplan (2026-04):** The indexed product URL is **`/schichtplan`** (serves `product_schichtplan_neu.php`). **`/schichtplan-neu`** **301 → `/schichtplan`** (QSA) — do **not** link to `/schichtplan-neu` in copy, FAQs, or JSON. The old template file **`v2/pages/product_shiftplan.php`** remains in the repo for reference only — **no clean URL** and **no links**; direct **`/v2/pages/product_shiftplan.php`** is **403**.

### Tools Pages
- **No trailing slash**
- Examples:
  - `/tools` ✓ (index)
  - `/tools/` ✗ (301 → `/tools`)
  - `/tools/elterngeldrechner` ✓
  - `/tools/arbeitszeitrechner` ✓
  - `/tools/elterngeldrechner/` ✗ (extra trailing slash)

### Template Pages
- **No trailing slash**
- Examples:
  - `/vorlagen` ✓ (index)
  - `/vorlagen/` ✗ (301 → `/vorlagen`)
  - `/vorlagen/schichtplan-excel-vorlage` ✓
  - `/vorlagen/abwesenheitsnotiz-vorlage` ✓
  - `/vorlagen/arbeitszeiterfassung-excel-vorlage` ✓
  - `/vorlagen/schichtplan-excel-vorlage/` ✗ (extra trailing slash)

### Industry Pages (Branchen)
- **No trailing slash**
- Examples:
  - `/branchen` ✓
  - `/branchen/gastronomie` ✓
  - `/branchen/gesundheitswesen` ✓
  - `/branchen/gastronomie/` ✗ (extra trailing slash; 301 redirects to canonical)

### Pagination Pages

**Blog pagination pages**: Keep all pages indexed, but de-optimize pages 2+ (2026 best practice)
- **All pages**: `index, follow` (allows content discovery)
- **Page 1**: Fully optimized title and description
- **Page 2+**: De-optimized with "Seite X" in title to avoid competing with page 1
- Examples:
  - `/insights/lexikon/` → Fully optimized title
  - `/insights/lexikon/page/11/` → Title includes "Seite 11" (de-optimized)
  - `/insights/ratgeber/page/2/` → Title includes "Seite 2" (de-optimized)

**Rationale** (2026 best practice): 
- **Avoid noindex** - Prevents search engines from discovering content through pagination links
- **De-optimize instead** - Pages 2+ have minimal keywords and generic titles to avoid competing with page 1
- **Self-referencing canonicals** - Each page points to itself (already implemented)
- **Proper navigation** - Numbered pagination links reduce crawl depth (already implemented)
- **Link equity flows** - All pages remain crawlable, preserving internal linking structure

### Self-Link Validation

Run the validation script to detect self-links:
```bash
php v2/scripts/dev-helpers/validate-self-links.php
```

To fix blog self-links (with backup):
```bash
php v2/scripts/blog/fix-blog-self-links.php --backup
```

### Canonical URL Validation

Run the validation script to check for violations:
```bash
php v2/scripts/blog/validate-canonical-urls.php
```

To automatically fix violations:
```bash
php v2/scripts/blog/validate-canonical-urls.php --fix
```

### Why

- Redirects add latency and extra requests.
- Search engines expect internal links to use the canonical URL; linking to a redirect is unnecessary and can dilute link equity.
- Consistency across the site avoids confusion and reduces the chance of new links using the wrong path.

### How to apply

1. **Before adding or changing an internal link**, check whether the path is the canonical one:
   - Look up the target in `.htaccess`: if a `RewriteRule` or `Redirect` sends that path *to* another path, the path you use in links must be the **destination**, not the source.
2. **Use the canonical URL in `href`, `urls` arrays, and any other link attributes.**

### Canonical URL reference (product and key pages)

These are the **canonical** paths. Use these in links. Do **not** use the shorter or legacy paths that redirect to them.

| Use this (canonical)     | Do not use (redirects) |
|-------------------------|------------------------|
| `/arbeitszeiterfassung` | `/zeiterfassung`       |
| `/schichtplan`          | `/schichtplanung` (redirects to schichtplan) |
| `/digitale-personalakte`| (use as-is)            |
| `/dokumentenmanagement` | `/dokumentenmanagement/` (trailing slash redirects to canonical) |
| `/checklisten`          | (use as-is)            |
| `/nano-ai`              | (use as-is)            |
| `/abwesenheiten`        | `/abwesenheiten/` (trailing slash redirects to canonical) |
| `/payroll`              | `/payroll/` (trailing slash redirects to canonical) |
| `/preise`               | `/preise-neu` (301 to `/preise`, QSA) |
| `/kunden`               | `/kunden-neu` (same file as `/kunden` today — **no** 301; still use **`/kunden`** in all internal links) |
| `/einladung`            | (use as-is; Cello referral landing page) |
| `/tools/arbeitszeitrechner` | `/tools/arbeitszeitrechner/` (trailing slash redirects) |
| `/tools/zuschlagsrechner`   | `/tools/zuschlagsrechner/` (trailing slash redirects) |
| `/tools/elterngeldrechner`  | `/tools/elterngeld-rechner` |
| `/vorlagen/schichtplan-excel-vorlage` | `/vorlagen/schichtplan-excel-vorlage/` (trailing slash redirects) |
| `/vorlagen/arbeitszeiterfassung-excel-vorlage` | `/vorlagen/arbeitszeiterfassung-vorlage` (301 redirects to excel-vorlage) |
| `/insights/ratgeber/gastronomie-mindestlohn/` | (use as-is; year-specific slug redirects handled by .htaccess) |
| `/insights/lexikon/personalentwicklung-und-weiterbildung/` | (canonical; mitarbeitergespraech post created 2026-02-25) |
| `/insights/dienstplan` | `/insights/dienstplan/` (trailing slash redirects to canonical) |
| `/insights/zeiterfassung` | `/insights/zeiterfassung/` (trailing slash redirects to canonical) |

When in doubt, search `.htaccess` for the path: if it appears on the **left** of a `Redirect` or `RewriteRule` that points elsewhere, do not use it in links; use the destination path instead.

### Scope

This applies to **all pages and assets** in the project: homepage, industry pages, product pages, comparison pages, blog content, lead-capture copy, sitemaps, and any new pages. New links must always use the canonical URL.

### No Self-Linking

**Never link a page to itself.** A page that links to its own URL provides no navigation value and can confuse users or appear as an error.

- **Templates:** `/vorlagen/personalbogen-vorlage` must not link to `/vorlagen/personalbogen-vorlage` within its content
- **Tools:** `/tools/arbeitszeitrechner` must not link to `/tools/arbeitszeitrechner` within its content
- **Downloads:** A download page must not link to its own URL
- **Blog:** A post at `/insights/lexikon/personalfragebogen/` must not link to that same URL

**Fix:** Replace self-links with plain text (no `<a>`). The user is already on the page; the mention adds context without needing a link.

**Example:**
- ❌ "Die [Personalbogen Vorlage](/vorlagen/personalbogen-vorlage) von Ordio ist kostenlos."
- ✓ "Die Personalbogen Vorlage von Ordio ist kostenlos." (on the personalbogen-vorlage page)

### Related

- Redirect definitions: `.htaccess`
- Redirect documentation: `docs/systems/landing-page-redirects/LANDING_PAGE_REDIRECTS.md`
