From 0a797a71fd3c030c90ff6cd438d43b09fd0bf8b5 Mon Sep 17 00:00:00 2001
From: Neophytis <37024002+Neophytis@users.noreply.github.com>
Date: Thu, 8 Oct 2026 20:14:59 +0200
Subject: [PATCH 1/4] fix(seo): canonical tags, apex sitemap and valid
robots.txt (BeWelcome/sysadmins-infra#654)
Since the move to bewelcome.org (www now redirects to the apex) Google
treats the apex as canonical, but the site still pointed at www:
- sitemap.xml listed only www URLs (all redirect), 8 of them dead
(/stats, /about/faq/0-6). Now 23 apex URLs, all 200, no stale lastmod.
- robots.txt had a relative Sitemap line (invalid) and Crawl-delay 10.
Now an absolute sitemap URL and no crawl delay.
- No page had a canonical tag, so ?gclid= and other query strings were
indexed as duplicates. Every full-page layout now includes
_canonical.html.twig, built from the route so defaults normalise
(/faq/1 and /faq give one URL), with a path-only fallback.
---
public/robots.txt | 7 +-
public/sitemap.xml | 159 ++++-------------------
templates/_canonical.html.twig | 4 +
templates/base-lite.html.twig | 1 +
templates/base.html.twig | 1 +
templates/home/home.html.twig | 1 +
templates/profile/profile.base.html.twig | 1 +
templates/search/searchmap.html.twig | 1 +
templates/security/login.html.twig | 1 +
9 files changed, 39 insertions(+), 137 deletions(-)
create mode 100644 templates/_canonical.html.twig
diff --git a/public/robots.txt b/public/robots.txt
index ed7d173c3a..4603063510 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -1,4 +1,3 @@
-User-agent: *
-Crawl-delay: 10
-Disallow:
-Sitemap: sitemap.xml
+User-agent: *
+Disallow:
+Sitemap: https://bewelcome.org/sitemap.xml
diff --git a/public/sitemap.xml b/public/sitemap.xml
index f0068f61b1..df37d52d70 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -1,133 +1,26 @@
-
-
-
- https://www.bewelcome.org/
- 2020-05-17T21:18:24+01:00
- 1.0
-
-
- https://www.bewelcome.org/signup
- 2020-05-17T21:18:24+01:00
- 1.0
-
-
- https://www.bewelcome.org/about
- 2020-05-17T21:18:27+01:00
- 1.0
-
-
- https://www.bewelcome.org/terms
- 2020-05-17T21:18:30+01:00
- 1.0
-
-
- https://www.bewelcome.org/privacy
- 2020-05-17T21:18:28+01:00
- 1.0
-
-
- https://www.bewelcome.org/impressum
- 2020-05-17T21:18:29+01:00
- 1.0
-
-
- https://www.bewelcome.org/safety
- 2020-05-17T21:18:30+01:00
- 1.0
-
-
- https://www.bewelcome.org/volunteer
- 2020-05-17T21:18:31+01:00
- 1.0
-
-
- https://www.bewelcome.org/about/faq
- 2020-05-17T21:18:31+01:00
- 0.8
-
-
- https://www.bewelcome.org/about/getactive
- 2020-05-17T21:18:31+01:00
- 0.8
-
-
- https://www.bewelcome.org/about/thepeople
- 2020-05-17T21:18:32+01:00
- 0.8
-
-
- https://www.bewelcome.org/stats
- 2020-05-17T21:18:32+01:00
- 1.0
-
-
- https://www.bewelcome.org/about/credits
- 2020-05-17T21:18:33+01:00
- 0.8
-
-
- https://www.bewelcome.org/login
- 2020-05-17T21:18:33+01:00
- 1.0
-
-
- https://www.bewelcome.org/safety/basics
- 2020-05-17T21:18:33+01:00
- 0.8
-
-
- https://www.bewelcome.org/safety/whattodo
- 2020-05-17T21:18:33+01:00
- 0.8
-
-
- https://www.bewelcome.org/safety/team
- 2020-05-17T21:18:34+01:00
- 0.8
-
-
- https://www.bewelcome.org/safety/faq
- 2020-05-17T21:18:34+01:00
- 0.8
-
-
- https://www.bewelcome.org/safety/tips
- 2020-05-17T21:18:34+01:00
- 0.8
-
-
- https://www.bewelcome.org/about/faq/2
- 2020-05-17T21:18:36+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/5
- 2020-05-17T21:18:35+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/0
- 2020-05-17T21:18:36+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/1
- 2020-05-17T21:18:36+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/3
- 2020-05-17T21:18:37+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/4
- 2020-05-17T21:18:36+01:00
- 0.6
-
-
- https://www.bewelcome.org/about/faq/6
- 2020-05-17T21:18:37+01:00
- 0.6
-
-
\ No newline at end of file
+
+
+ https://bewelcome.org/
+ https://bewelcome.org/signup
+ https://bewelcome.org/login
+ https://bewelcome.org/about
+ https://bewelcome.org/about/getactive
+ https://bewelcome.org/about/thepeople
+ https://bewelcome.org/about/credits
+ https://bewelcome.org/faq
+ https://bewelcome.org/faq/2
+ https://bewelcome.org/faq/4
+ https://bewelcome.org/faq/6
+ https://bewelcome.org/faq/7
+ https://bewelcome.org/faq/9
+ https://bewelcome.org/safety
+ https://bewelcome.org/safety/basics
+ https://bewelcome.org/safety/whattodo
+ https://bewelcome.org/safety/team
+ https://bewelcome.org/safety/faq
+ https://bewelcome.org/safety/tips
+ https://bewelcome.org/volunteer
+ https://bewelcome.org/terms
+ https://bewelcome.org/privacy
+ https://bewelcome.org/impressum
+
diff --git a/templates/_canonical.html.twig b/templates/_canonical.html.twig
new file mode 100644
index 0000000000..6968f0841e
--- /dev/null
+++ b/templates/_canonical.html.twig
@@ -0,0 +1,4 @@
+{# Self-referencing canonical without query string (#654 in BeWelcome/sysadmins-infra).
+ Built from the route so defaults normalise (/faq/1 and /faq share one URL). #}
+{% set canonical_route = app.request.attributes.get('_route') %}
+
diff --git a/templates/base-lite.html.twig b/templates/base-lite.html.twig
index d2c167b9da..9d803e1d6f 100644
--- a/templates/base-lite.html.twig
+++ b/templates/base-lite.html.twig
@@ -20,6 +20,7 @@
+ {% include '_canonical.html.twig' %}
diff --git a/templates/base.html.twig b/templates/base.html.twig
index 7f9a29f165..6bafebf0b2 100644
--- a/templates/base.html.twig
+++ b/templates/base.html.twig
@@ -19,6 +19,7 @@
+ {% include '_canonical.html.twig' %}
{% block redirect %}{% endblock %}
diff --git a/templates/home/home.html.twig b/templates/home/home.html.twig
index c8c3687b09..3c5f32dd78 100644
--- a/templates/home/home.html.twig
+++ b/templates/home/home.html.twig
@@ -11,6 +11,7 @@
BeWelcome - {{ 'home.headline.bewelcome.cultural' | trans }}
+ {% include '_canonical.html.twig' %}
{% include 'webpreview.html.twig' %}
diff --git a/templates/profile/profile.base.html.twig b/templates/profile/profile.base.html.twig
index aac78ffe9a..70c30c2cb3 100644
--- a/templates/profile/profile.base.html.twig
+++ b/templates/profile/profile.base.html.twig
@@ -19,6 +19,7 @@
+ {% include '_canonical.html.twig' %}
{% block redirect %}{% endblock %}
diff --git a/templates/search/searchmap.html.twig b/templates/search/searchmap.html.twig
index 660322c649..cfe39bfad8 100644
--- a/templates/search/searchmap.html.twig
+++ b/templates/search/searchmap.html.twig
@@ -9,6 +9,7 @@
{{ title }} - BeWelcome
+ {% include '_canonical.html.twig' %}
{{ encore_entry_link_tags('bewelcome') }}
diff --git a/templates/security/login.html.twig b/templates/security/login.html.twig
index 4d80528776..8ffaa13b9d 100644
--- a/templates/security/login.html.twig
+++ b/templates/security/login.html.twig
@@ -14,6 +14,7 @@
{{ 'login' | trans }} | BeWelcome
+ {% include '_canonical.html.twig' %}
From db3928bb339bdaecd8d2b354ef4815a8ac1f600f Mon Sep 17 00:00:00 2001
From: Neophytis <37024002+Neophytis@users.noreply.github.com>
Date: Thu, 8 Oct 2026 20:26:08 +0200
Subject: [PATCH 2/4] fix(seo): canonical on legacy pages, none on error pages
(BeWelcome/sysadmins-infra#654)
/signup and other legacy pages render through roxpage/page.php, which had
no canonical. It now gets one that keeps the query string (legacy pages
may need it) and only drops tracking parameters (utm_*, gclid, fbclid...).
The Twig partial drops the path fallback: error pages render without a
route, so they no longer get a canonical.
---
templates/_canonical.html.twig | 9 ++++++---
templates/shared/roxpage/page.php | 13 +++++++++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/templates/_canonical.html.twig b/templates/_canonical.html.twig
index 6968f0841e..c2f5adc52a 100644
--- a/templates/_canonical.html.twig
+++ b/templates/_canonical.html.twig
@@ -1,4 +1,7 @@
-{# Self-referencing canonical without query string (#654 in BeWelcome/sysadmins-infra).
- Built from the route so defaults normalise (/faq/1 and /faq share one URL). #}
+{# Self-referencing canonical without query string (BeWelcome/sysadmins-infra#654).
+ Built from the route so defaults normalise (/faq/1 and /faq share one URL).
+ Error pages are rendered without a route, so they get no canonical. #}
{% set canonical_route = app.request.attributes.get('_route') %}
-
+{% if canonical_route %}
+
+{% endif %}
diff --git a/templates/shared/roxpage/page.php b/templates/shared/roxpage/page.php
index 07f8897c27..a2c9e7d47d 100644
--- a/templates/shared/roxpage/page.php
+++ b/templates/shared/roxpage/page.php
@@ -8,6 +8,19 @@
+
+
From 180e94dc3bc841f4885410d84eba9f2a74b606a3 Mon Sep 17 00:00:00 2001
From: Neophytis <37024002+Neophytis@users.noreply.github.com>
Date: Thu, 8 Oct 2026 20:34:45 +0200
Subject: [PATCH 3/4] fix(seo): legacy canonical belongs in
PageWithHTML::head() (BeWelcome/sysadmins-infra#654)
templates/shared/roxpage/page.php is not loaded anywhere; legacy pages
such as /signup render their head through tools/page/html.page.php. Move
the canonical there and build it from baseuri, which already carries the
right scheme and host.
---
templates/shared/roxpage/page.php | 13 -------------
tools/page/html.page.php | 16 ++++++++++++++++
2 files changed, 16 insertions(+), 13 deletions(-)
diff --git a/templates/shared/roxpage/page.php b/templates/shared/roxpage/page.php
index a2c9e7d47d..07f8897c27 100644
--- a/templates/shared/roxpage/page.php
+++ b/templates/shared/roxpage/page.php
@@ -8,19 +8,6 @@
-
-
diff --git a/tools/page/html.page.php b/tools/page/html.page.php
index 9a4147a3f0..9f8f11ea81 100644
--- a/tools/page/html.page.php
+++ b/tools/page/html.page.php
@@ -333,12 +333,28 @@ protected function head()
+
includeStylesheets();
$this->includeCustomElements();
$this->_tr_buffer_header = $this->getWords()->flushBuffer();
}
+ /**
+ * Self-referencing canonical (BeWelcome/sysadmins-infra#654). Legacy pages may rely on the
+ * query string, so only tracking parameters are dropped.
+ */
+ protected function getCanonicalUrl($baseuri)
+ {
+ $parts = parse_url($_SERVER['REQUEST_URI'] ?? '/');
+ parse_str($parts['query'] ?? '', $query);
+ $query = array_filter($query, function ($key) {
+ return !preg_match('/^(utm_.*|gclid|gbraid|wbraid|fbclid|msclkid)$/', $key);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return rtrim($baseuri, '/') . ($parts['path'] ?? '/') . ($query ? '?' . http_build_query($query) : '');
+ }
+
protected function getPagePermalink() {
return 'index';
}
From 230dacee3372fe96058f2d7e9b62791207ed5bfe Mon Sep 17 00:00:00 2001
From: Neophytis <37024002+Neophytis@users.noreply.github.com>
Date: Thu, 8 Oct 2026 22:58:57 +0200
Subject: [PATCH 4/4] fix(seo): add the four public pages from develop's
sitemap config (BeWelcome/sysadmins-infra#654)
/about/statistics, /about/commentguidelines, /press-information and
/feedback are listed in config/sitemap.yaml on develop (#476) and return
200; the static sitemap now has them too.
---
public/sitemap.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/public/sitemap.xml b/public/sitemap.xml
index df37d52d70..476e64ae75 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -7,6 +7,10 @@
https://bewelcome.org/about/getactive
https://bewelcome.org/about/thepeople
https://bewelcome.org/about/credits
+ https://bewelcome.org/about/statistics
+ https://bewelcome.org/about/commentguidelines
+ https://bewelcome.org/press-information
+ https://bewelcome.org/feedback
https://bewelcome.org/faq
https://bewelcome.org/faq/2
https://bewelcome.org/faq/4