marco
December 22, 2021, 1:30pm
1
Hi,
I have a weird behaviour, after renaming a page (and also updating the slug) in a multilang site environment.
What I would expect: Old URL is not working anymore and end up on a 404 page.
What happens: Old URL is still accessible. The new URL is accessible as well.
I already tried with an emptied browser cache and checked for any weird redirects.
Any idea where to start search for the bug?
texnixe
December 22, 2021, 3:08pm
2
Which Kirby version are you using? What are the steps to reproduce the issue? Can you yourself reproduce them in a fresh Starterkit after adding languages?
marco
January 25, 2022, 9:08am
3
Sorry for the late reply!
I’m using version 3.5.3.1. I just tried to reproduce it in a fresh starterkit and i experience the same behaviour.
The steps to reproduct it:
Create a new page in the default language
Publish the page
Switch in the admin panel to the secondary language
Change the title of the page (but not the slug yet)
Preview the page and copy the url for later
Change the slug of the page
Preview the page
Open the URL from step 5
Outcome: Both url’s work
Expected behaviour: The old url should not work anymore
marco
January 25, 2022, 10:33am
5
And this would be the expected behaviour in the end, which is not implemented yet?
opened 07:55PM - 19 Jul 21 UTC
type: bug 🐛
## Basic example
**URLs:**
```
/page/subpage
/de/seite/unterseite
```
…
**Request mapping right now:**
```
/page/subpage ✅
/de/seite/unterseite ✅
/de/page/subpage -> serves the page /de/seite/unterseite
/de/seite/subpage -> same here
/de/page/unterseite -> same here
```
**Expected behavior:**
The last three examples should be `HTTP 302` redirects to the canonical URL `/de/seite/unterseite`.
## Complex example
This works at the moment and there needs to be a unit test to verify that we don't break this behavior.
**URLs:**
```
/page1
/de/seite1
/page2
/de/page1 (translation of page2!)
```
**Expected routing:**
```
/page1 ✅
/de/seite1 ✅
/page2 ✅
/de/page2 -> 302 to /de/page1
/de/page1 ✅ (should *not* redirect to /de/seite1, which is a different page)
```
## Background context
See #2257.
marco
January 25, 2022, 10:40am
7
Can you give a rough indication of when this will be fixed?
texnixe
January 25, 2022, 11:06am
8
Sorry, no, I can’t. This issue has been lying around for a while now.
You could probably create your own route that does the redirecting. Maybe not a 404, but a 302 redirect for existing page.
marco
February 1, 2022, 7:33am
10
Sorry that i get back to this again… After talking to our SEO team, this really might become a problem. It will lead to duplicate content and cannibalisation of the content, once the wrong URL’s also will be indexed. In terms of SEO this should maybe have a rather high prio…
You wrote about creating my own route for the redirecting. Could you give me some more guidance on how you would do it to create a workaround for now?
Would you make fixed redirect routes for URL’s that are affected? Or is there a more dynamic approach?
A small plugin should work for your SEO:
<?php
use Kirby\Cms\App;
use Kirby\Http\Route;
use Kirby\Http\Uri;
App::plugin('rasteiner/canonical', [
'pageMethods' => [
'canonical' => function () {
$siteUri = new Uri(site()->url());
$host = option('rasteiner.canonical.host', $siteUri->host());
$scheme = option('rasteiner.canonical.scheme', $siteUri->scheme());
$uri = new Uri($this->url());
$uri->setHost($host);
$uri->setScheme($scheme);
return $uri->toString();
}
],
'hooks' => [
'route:after' => function(Route $route, string $path, string $method, mixed $result, bool $final) {
if(is_a($result, 'Kirby\Cms\Page') === true) {
$canonical = $result->canonical();
if($canonical !== null) {
header('Link: <' . $canonical . '>; rel="canonical"');
}
}
}
]
]);
It doesn’t redirect, but serves the page right away and specifies the canonical address of the page. This should be enough to consolidate duplicates.
You can also use it to specify a canonical host (like with or without www.
) and scheme (http
or https
) in your config:
<?php
return [
'rasteiner.canonical.host' => 'example.com',
'rasteiner.canonical.scheme' => 'https',
];
PS:
haven’t thoroughly tested this, maybe check if it gives the expected results in your dev tools network tab
PPS:
you could also be extra sure engines get the message by including a <link>
tag into your template head section:
<link rel="canonical" href="<?= $page->canonical() ?>" />