On this page
- The Golden Rule
- Moving Pages (Topic Restructure)
- The Right Order
- Setting Up Redirects
- After Restructure
- Merging Pages
- Manual Merges
- Deleting Pages
- Redirect Chains
- Wire Flattens Chains Automatically
- RULE-61: Redirect Chain Lint
- Prevention
- Multi-Language URL Changes
- Monitoring After URL Changes
- Quick Reference
Every URL change is a risk. Google has indexed the old URL, backlinks point to it, and users may have bookmarked it. Wire handles redirects automatically for merges and differentiations, but topic restructures and manual moves require deliberate planning. This guide covers every scenario.
The Golden Rule
Every old URL must resolve to the correct final destination in one hop. No chains (A to B to C), no dead ends (404), no soft redirects (everything pointing to the homepage).
Wire generates 301 redirects as both _redirects (Netlify/Cloudflare format) and HTML fallback pages with <meta http-equiv="refresh"> and <link rel="canonical">. All redirects live in .wire/redirects.yml.
Moving Pages (Topic Restructure)
When you reorganize a flat site into topic directories, every page gets a new URL:
/alte-seite/ → /ki-technologie/alte-seite/
/andere-seite/ → /dokumente/andere-seite/
The Right Order
Deduplicate before restructuring. This is the most common mistake. Run the full audit and deduplicate cycle while pages are still flat:
python -m wire.chief data
python -m wire.chief audit
python -m wire.chief deduplicate
Why this order matters:
Fewer redirects. If you merge A into B first, then move B to its topic, you need one redirect (A to B's new location). If you move both first, then merge, you get a redirect chain: A's old URL to A's new URL to B's new URL. Wire flattens chains at build time, but avoiding them is cleaner.
GSC data stays valid. Wire's overlap detection uses GSC keyword data stored by (topic, slug) pairs. When you move a page to a new topic, Wire registers it as a new page with no search history. The old data becomes orphaned. Running deduplication first means Wire makes merge/differentiate decisions with full keyword data.
Cross-topic merges work but create cross-topic redirects. Wire allows merging pages across topics - the donor gets a redirect to the keeper's topic. But this means content moves between silos, which may not match your intended topic structure. Deduplicating first keeps the decision cleaner.
Setting Up Redirects
Add redirects to .wire/redirects.yml before moving files. Wire's add_redirect() function handles this, or you can edit the YAML directly:
- from: /alte-seite/
to: /ki-technologie/alte-seite/
reason: "topic restructure"
date: "2026-03-13"
For large restructures (500+ pages), generate the redirects programmatically. Every old URL needs exactly one entry pointing to the new location.
After moving files:
python -m wire.chief sanitize # Fix broken internal links
python -m wire.build # Verify build + generate redirects
After Restructure
Migrate your existing GSC data to the new URL structure, then re-register pages:
python -m wire.chief migrate-gsc # Rekey GSC data using .wire/redirects.yml
python -m wire.chief data # Re-register pages + fetch fresh data
migrate-gsc reads .wire/redirects.yml and updates Content rows in the GSC database to match the new topic/slug/path. All keyword and snapshot history is preserved. If the new page already has some data (from a recent fetch), the old data is merged in.
For new URLs where Google hasn't transferred signals yet, Wire's GSC fetch automatically tries the old URL (via redirects) as a fallback. This means the audit sees data immediately after a restructure, not after waiting 2-4 weeks for Google to re-index.
Merging Pages
Wire's deduplicate command handles merges automatically. When two pages cannibalize each other (overlap ratio >0.4, traffic skew >0.7), Wire:
- Selects the stronger page as keeper (higher composite score from impressions, position, clicks, keyword count)
- Absorbs the donor's unique content into the keeper
- Archives the donor (
index.mdbecomesindex.md.archived) - Creates a redirect from donor URL to keeper URL
- Registers the redirect in
.wire/redirects.yml
The merge guard prevents content loss: if the merged output is less than 80% of the keeper's original body, Wire writes to .preview only and does not archive the donor.
Manual Merges
If you know two pages should be merged but Wire's thresholds don't trigger it (not enough shared keywords yet, or pages are in different topics):
- Manually combine the content into the keeper page
- Archive the donor: rename
index.mdtoindex.md.archived - Add the redirect:
from wire.tools import add_redirect
add_redirect("/old-donor-path/", "/keeper-path/", reason="manual merge")
Or edit .wire/redirects.yml directly.
Deleting Pages
Wire does not have a delete command. Deletion is a manual decision with SEO consequences. Before deleting:
- Check GSC data. Does the page get any impressions? Even 10 impressions/month means Google values it. Consider merging instead.
- Check inbound links. Run
python -m wire.chief auditand look for pages that link to the one you want to delete. Update those links first. - Add a redirect. Point the deleted URL to the most relevant surviving page, not the homepage (that is a soft 404 in Google's eyes).
# .wire/redirects.yml
- from: /deleted-page/
to: /relevant-surviving-page/
reason: "page removed, content covered by surviving page"
date: "2026-03-13"
If no relevant page exists, let it 404. A clean 404 is better than a misleading redirect.
Redirect Chains
A redirect chain is when URL A redirects to URL B, which redirects to URL C. Chains happen when:
- A page is moved (restructure), then its new location is merged into another page
- A page is merged, then the keeper is later moved to a different topic
- Manual redirects are added without checking existing redirect targets
Wire Flattens Chains Automatically
At build time, generate_redirects() detects chains and flattens them. If .wire/redirects.yml contains:
- from: /a/
to: /b/
- from: /b/
to: /c/
Wire generates the output as:
/a/ /c/ 301
/b/ /c/ 301
The build log warns about every chain it flattens:
WARNING: Redirect chain flattened: /a/ → /b/ → /c/ (now /a/ → /c/)
RULE-61: Redirect Chain Lint
The build linter (RULE-61) also detects chains in the HTML output as a safety net. If a redirect HTML page points to another redirect HTML page, the linter flags it. This catches chains from manual HTML redirect pages that bypass .wire/redirects.yml.
Prevention
The best way to avoid chains is to follow the right order:
- Deduplicate (merge/differentiate) while pages are flat
- Restructure into topics
- Add redirects from old flat URLs to new topic URLs
If you must restructure first:
- Wire's chain flattening handles it at build time
- But the
.wire/redirects.ymlfile keeps the intermediate entries, making it harder to audit later
Multi-Language URL Changes
For multi-language sites, each language has its own URL space:
/de/alte-seite/ → /de/ki-technologie/alte-seite/
/en/old-page/ → /en/ai-technology/old-page/
Restructure each language independently. German topics do not need to match English topics. Add redirects per language. The hreflang system handles cross-language linking automatically if pages declare their alternates in frontmatter.
Monitoring After URL Changes
After any URL change, monitor these signals over 2-4 weeks:
- Build linter. RULE-33 (broken internal links) and RULE-61 (redirect chains) catch issues immediately at build time.
- GSC data. Run
python -m wire.chief dataweekly. Watch for the new URLs appearing in search results and the old URLs dropping off. - Audit. Run
python -m wire.chief auditto check for new orphan pages (pages with no inbound links after restructure) and new cannibalization pairs.
The transition period is 2-6 weeks depending on crawl frequency. During this time, audit results will show limited data for moved pages. This is expected. Do not make additional URL changes during this period - let Google settle.
Quick Reference
| Action | Command | Redirect? | Who creates it? |
|---|---|---|---|
| Merge (auto) | wire.chief deduplicate | Yes | Wire automatic |
| Merge (manual) | Edit files + add_redirect() | Yes | You |
| Move to topic | Move files + edit .wire/redirects.yml | Yes | You |
| Delete | Remove file + edit .wire/redirects.yml | Recommended | You |
| Rename slug | Move directory + edit .wire/redirects.yml | Yes | You |
| Change domain | Update site_url in wire.yml | Server-level | Your server config |
All redirects end up in .wire/redirects.yml and are generated as 301s at build time. Wire flattens chains automatically. The linter catches anything that slips through.