We were renaming the products in a client's Odoo shop. Thousands of them were named by part number, which tells a shopper nothing, so we built descriptive names from each product's attributes. Then we hit the catch: in Odoo, a product's URL comes from its name. Renaming thousands of products would have given thousands of pages a new address at once. So we built a module that keeps the URL when the name changes. The rename is live, and every product kept its address.
- Odoo builds the URL of a product, an eCommerce category or a blog post from its name. Rename it and the URL changes on save, with no warning.
- The module can keep the old address and forward to the new one, so links keep working. But the URL Google indexed, the one in your newsletter and the one in your analytics are now redirects.
- Website Permalink keeps the published URL when you rename. When you do want a new one, it asks, and leaves a 301 you can see in your Redirects list.
- Odoo 18, 19 and 20. Running on this site today. Code on GitHub.
Why your URL moves
Odoo makes a page's address from its name plus its record ID. Our demo post, "Permalink Demo: Original Title," is record 34, so it lives at /blog/permalink-demo-original-title-34. Products and eCommerce categories work the same way under /shop.

Change the name and Odoo rebuilds the address when you save. Fix a typo in a product name, add the year to a blog title, rename a category for a seasonal push: each one gives the page a new URL. The form doesn't mention it.
Links still work, but the address moved
Odoo only needs the ID at the end of the URL. Visit the old address and it sends you to the new one with a 301, so nobody hits a 404.
What changes is the address itself:
- Google indexed the old URL. Now it finds a redirect, recrawls, and updates its index. Until then, search results point at a redirect.
- Your analytics splits the page's history across two URLs.
- Every link you've shared, in newsletters, LinkedIn posts, ads and partner sites, now goes through an extra hop.
- Rename a page three times and it has had four URLs.
Most renames are about wording, and nobody meant to move the page.
What we built
Website Permalink keeps a page's URL when you rename it, once it has been published. Here's the flow on our own blog, with a throwaway demo post.
1. Rename the post

The form now shows the URL and a URL Slug field. "Follows the name" means the URL is still built from the title.

Change the title and a notice appears at the top of the form: "Website Permalink kept this page's URL," with the URL under it.

2. Save. Keep URL is the default.

Saving opens a short pop-up. Keep URL is already selected, so one click on Save finishes the job.
3. New title, same URL

The URL Slug now holds the old slug. That's what pins the URL in place.

On the website, the post has its new title and the same address.
4. When you do want a new URL

Pick "Change URL to match the new name." The 301 checkbox turns on, already ticked.

The URL follows the new title.

The redirect shows up under Website, Configuration, Redirects, named after the page, so you can see what moved.

Paste the old link into a new tab and it lands on the new URL.
The small print
- Drafts follow their name. A page that's never been published has no links pointing at it, so its URL keeps matching its title until the first publish. After that, the URL stays put, even if you unpublish it later.
- Closing the tab asks first. Close the tab with an unsaved rename and the browser's "Leave site?" prompt stops you, so a rename can't get saved without the choice.
- Imports, the API and AI agents keep the URL. Anything that isn't a person in the form skips the pop-up and keeps the URL. The field's help text tells AI agents working through the API or an MCP server to ask you before changing a URL.
- Editing the slug by hand adds a 301. Type a new URL Slug and the old URL redirects to it, unless you untick the box.
- Redirects stay short. Rename A to B, then B to C, and A goes straight to C. Rename back to A and the reverse redirect is removed.
- Website pages aren't touched. Odoo already stores their URL separately from their name.
Three modules, install one

Search Apps for "permalink" and you'll see three. Install Website Permalink. The Blog and eCommerce add-ons install themselves when those apps are on your database, so each add-on only shows up on databases that have its app.
What it won't do
- Moving a post to another blog. Standard Odoo puts the blog's name in the post URL (
/blog/news-1/my-post-5), so moving a post between blogs changes its URL, and the module doesn't count that as a rename. Our Blog Flat URLs module takes the blog out of the URL, so the problem goes away. - Big catalogs, unmeasured. Each language has its own URL, so a rename pins one per installed language. We haven't benchmarked bulk renames on large multi-language catalogs. Test before rolling it out to one.
- Odoo Online. Custom modules need Odoo.sh or on-premise.
Next: flat shop URLs
In Odoo 20, category URLs nest: /shop/category/furniture-6/chairs-7. Move Chairs under a different parent and its URL changes, along with every subcategory under it. Website Permalink adds 301s for those moves, but the nesting is the real problem. We already flattened the blog with Blog Flat URLs. The shop version would serve /category/name and /product/name. If you'd use it, tell us.
Install it
Website Permalink works on Odoo 18, 19 and 20 and needs only the Website app. It's free under LGPL-3. Code, install steps and docs: github.com/19prince/website_permalink. Want help putting it on your database? Get in touch. More of what we build is in the Lab.