Friend for Craft CMS

Free for Craft CMS 5

Every dead URL has a friend

A 404 is usually a visitor holding a URL that used to work. The slug moved, or the page went and its parent survived. Friend works out which, finds the entry they were after, and sends them there — but only when the match clears a threshold you set, and with a log of every guess it made.

Friend

See exactly why

The tester — in the control panel or on the command line — resolves a URL as though it had just 404'd and shows the whole decision: every rule, why it matched or declined, and each candidate's score broken into slug, title and path. Nothing is cached, logged or redirected.

bash
$ php craft friend/match/test blog/2019/our-new-offices

  blog/2019/our-new-offices
  site: Main   slug: our-new-offices   tokens: blog, 2019, our, new, office

  skipped          Ignore probes — The URI does not match `re:^wp-`.
  matched          Similar entries (best 92.3) — Redirecting to news/our-new-office.

  Candidates
     92.3  /news/our-new-office      slug 0.87  title 1.00  path 0.00  [slug,tokens,search]
     41.0  /news/office-move         slug 0.44  title 0.40  path 0.00  [search]

  → 302 https://example.com/news/our-new-office

Features

Retrieval for recall, scoring for precision, and a threshold between them — not whatever the database happened to return first.

Rules, in order

Each rule says when it applies, which elements it may point to, and how sure it must be. The first rule that decides wins — and a rule that finds nothing above its threshold has not decided, so the next one gets a turn.

  • Redirect, offer suggestions, or match and deliberately do nothing
  • Limit by site, URI pattern, segment count, section, entry type or category group

Four ways to find a candidate

Exact slug, word overlap on slug and title, Craft's own search index, and the nearest surviving ancestor page — in any combination, per rule.

  • /blog/our-new-office finds /news/our-new-office
  • /services/seo-audits falls back to /services

A score you can read

Every candidate is re-ranked as a weighted blend of slug, title and path similarity. The weights are yours, and the threshold — 55 by default — is the whole safety mechanism.

A 404 log worth opening

One row per site and URI with a hit counter, so the top of the list is what is actually broken. Each row records the target chosen, its score, the rule that chose it, and whether the visitor was moved.

  • Pruned by age and by row count during garbage collection

Pins for the one it gets wrong

Press Pin on a log row and that answer is stored, checked before any rule, for the cost of one indexed lookup — fixing one URL without making the rules worse for every other.

Guards that never move

Site GET and HEAD requests only — never the control panel, an action request, a preview or the homepage. Scanner paths and missing images, scripts and stylesheets stay 404, and no URL is ever sent back to itself.

  • Ignored patterns and extensions are editable
  • Stands down when config/redirects.php already covers the URL

Or just suggest

Set a rule to Suggestions — or let one decline — and the 404 stands, with a ranked "did you mean" list for your error template. Every tag takes an optional URI, so it works on any page.

twig
{% set suggestions = craft.friend.suggestions(5) %}

{% if suggestions %}
    <h2>Did you mean…</h2>
    <ul>
        {% for candidate in suggestions %}
            <li><a href="{{ candidate.url }}">{{ candidate.title }}</a></li>
        {% endfor %}
    </ul>
{% endif %}

Frequently Asked Questions

The questions worth answering before you install it.

Free, and ready for the next 404

One composer command, no licence key, and a sensible rule already switched on. Open the tester, try a few dead URLs, and see what it would do.