Smarter redirects when editors trash content in Umbraco

umbraco ai package hackathon backoffice

Last week, a good handful of Umbraco developers met up at Ecreo’s office in Odense for an Umbraco AI Hackathon, guided by the DevRel team from Umbraco HQ. One of the ideas Sebastiaan Janssen pitched on the day was an old one: when an editor trashes a published page, the URL it used to live on quietly stops working, and Umbraco doesn’t help you redirect it anywhere.

I recognised the idea instantly. I’m fairly sure I saw an issue about exactly this on the old CodePlex tracker, somewhere around the time built-in URL tracking shipped in Umbraco 7.5. It’s been on my mental wishlist for roughly a decade. A hackathon day felt like a good excuse to finally build it.

The result is a new package: Umbraco.Community.SmartRedirectSuggester.

What it does

When an editor trashes a published document, the package replaces the default trash dialog with one that:

  • captures the document’s current URL (and the URLs of every published descendant, if you trash a parent)
  • asks an Umbraco searcher to suggest likely redirect targets for each of those URLs
  • lets the editor confirm, change, or skip each target
  • registers the chosen redirects in Umbraco’s built-in URL tracker after the trash succeeds

Single trash with suggested redirect

The wrong turn: hooking into a post-trash event

My first instinct was to keep the standard trash flow intact and just react afterwards. My AI agent helpfully pointed at a client-side backoffice notification that fires once a document has been moved to the recycle bin. I wired up a modal to pop on that event and got something running quickly.

It took embarrassingly little testing to realise the obvious problem.

By the time my modal opened, the document was already in the recycle bin. Its published route was gone. GetUrl(...) had nothing to return. I could happily ask the user to pick a redirect target, but I’d already lost the redirect source. The very URL I needed to redirect from was gone. The thing I wanted to preserve had been forgotten between the click and the callback.

The right turn: replacing the trash action

Instead of listening for a post-trash event, I needed to take over the trash action itself. The new backoffice makes that fairly clean. Entity actions are extension points, and an extension can declare that it overwrites an existing alias. Point that at the core Umb.EntityAction.Document.RecycleBin.Trash alias (and its bulk equivalent), reuse the same repositories and conditions as the original, and the extension registry quietly swaps my action in for the built-in one. Only the UX is replaced, not the authorisation rules.

With that hook in place, the flow becomes:

  1. Prepare. When the user clicks “Trash”, the action calls a prepare API endpoint that expands the selection to include published descendants, captures their current URLs, and asks for redirect suggestions. Crucially, this happens while the documents are still published and routable.
  2. Trash. The action runs the standard trash logic and the document(s) move to the recycle bin.
  3. Commit. Once the trash succeeds, the action calls a commit endpoint that registers the chosen redirects against the cached old URLs.

The legacy URLs are kept in a short-lived server-side cache between prepare and commit. That’s how the package can still create redirects after the routes have technically vanished.

AI suggestions, with a sensible fallback

For the actual suggestion step, the package asks Umbraco’s search infrastructure for similar pages. It tries two searchers in order:

  1. UmbAI_Search, provided by Umbraco.AI.Search. This is the preferred path. In my experience, AI-powered search matches “this page is about a discontinued product” to “this is the page about its successor” far better than keyword search ever does.
  2. Umb_Content, provided by Umbraco.Cms.Search. The non-AI fallback. Faster, free, and lower-quality, but still useful, especially for bulk operations.

If neither searcher is registered, the package still loads and the modal still opens. The editor just gets an empty suggestion list and can pick a target manually or skip the redirect.

Bulk trashes and the 500-node moment

The package handles bulk trashes too. There’s an entity bulk action on document collections, plus the implicit “trash a parent and take its descendants with it” case. Both go through the same prepare step, which means a single bulk trash can produce dozens or hundreds of suggestion lookups.

While testing, I trashed about 500 nodes in one go to see what would happen. It worked. The modal listed every URL with its suggested target and let me eyeball them.

Then I remembered I’d done all 500 lookups against UmbAI_Search.

I haven’t gone back to look at my AI billing for that day, and I’d rather not. But this is the headline gotcha of the package: AI searchers are great for accuracy, and potentially expensive when you point them at a lot of content at once. The Umb_Content fallback exists partly because of this. It’s a deliberate feature, not just a degraded mode.

Heads up: if you’re trashing a parent with a large subtree, be aware that every published descendant becomes a search call. With UmbAI_Search enabled, that’s a real cost.

How to install

The package needs Umbraco 17 and at least one searcher.

dotnet add package Umbraco.Community.SmartRedirectSuggester
dotnet add package Umbraco.Cms.Search

For AI-powered suggestions, also install:

dotnet add package Umbraco.AI.Search

That’s it. Restart the site, trash a published page, and the new dialog takes over.

Multiple trashes with suggested redirects

Changing the redirect for an individual item in a bulk operation

Redirect management overview

What I’d change

A hackathon day buys you a working package. It doesn’t buy you every nice-to-have. The thing I’d add next is a guard against the bulk-AI cost trap:

  • A config switch to force Umb_Content regardless of whether Umbraco.AI.Search is installed.
  • Or, better, a soft prompt in the modal when the bulk count crosses a threshold: “You’re about to ask AI Search for suggestions on 500 documents. Use the non-AI fallback instead?”

Both feel more honest than just hoping editors notice the bill at the end of the month.

Final thoughts

This is the kind of feature that’s been sitting in Umbraco’s “yeah, that’d be nice” pile for years, and it took a hackathon day with a clear pitch and good company to finally push it out the door. Thanks to the Umbraco HQ DevRel team for organising, to Sebastiaan Janssen for the idea, and to Ecreo for hosting.

The repo, with installation docs, screenshots and the full source, lives at skttl/umbraco-smart-redirect-suggester. You are welcome to create an issue, especially if you have opinions on how the bulk-AI guardrails should look.