diff --git a/czech_inspirational/migrations/0007_czechinspirationalhomepage_title_suffix.py b/czech_inspirational/migrations/0007_czechinspirationalhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..890ebfb8d35416003bdb80e79e6b3b2bac9ab532
--- /dev/null
+++ b/czech_inspirational/migrations/0007_czechinspirationalhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("czech_inspirational", "0006_czechinspirationalchapterpage_extra_text"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="czechinspirationalhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/czech_inspirational/models.py b/czech_inspirational/models.py
index 51c81fc7dba6870836975415034aefe6ba2e7a36..dc887f35609d782ee24acb6a9c733137670774c3 100644
--- a/czech_inspirational/models.py
+++ b/czech_inspirational/models.py
@@ -15,13 +15,19 @@ from wagtail.documents.edit_handlers import DocumentChooserPanel
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
-from shared.models import SubpageMixin
+from shared.models import (
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+)
 from shared.utils import subscribe_to_newsletter
 from tuning import admin_help
 from uniweb.constants import RICH_TEXT_FEATURES
 
 
-class CzechInspirationalHomePage(Page, MetadataPageMixin):
+class CzechInspirationalHomePage(
+    Page, ExtendedMetadataHomePageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     buy_book_url = models.URLField("URL pro nákup knihy", blank=True, null=True)
@@ -53,6 +59,7 @@ class CzechInspirationalHomePage(Page, MetadataPageMixin):
         MultiFieldPanel(
             [
                 FieldPanel("matomo_id"),
+                FieldPanel("title_suffix"),
             ],
             "nastavení webu",
         ),
@@ -113,7 +120,9 @@ class CzechInspirationalHomePage(Page, MetadataPageMixin):
         return context
 
 
-class CzechInspirationalChaptersPage(Page, SubpageMixin, MetadataPageMixin):
+class CzechInspirationalChaptersPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     ### PANELS
@@ -158,7 +167,9 @@ class CzechInspirationalChaptersPage(Page, SubpageMixin, MetadataPageMixin):
         return context
 
 
-class CzechInspirationalChapterPage(Page, SubpageMixin, MetadataPageMixin):
+class CzechInspirationalChapterPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     number = models.IntegerField("číslo kapitoly", default=0)
@@ -225,7 +236,9 @@ class CzechInspirationalChapterPage(Page, SubpageMixin, MetadataPageMixin):
         return context
 
 
-class CzechInspirationalDownloadPage(Page, SubpageMixin, MetadataPageMixin):
+class CzechInspirationalDownloadPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     book_file = models.ForeignKey(
diff --git a/district/migrations/0060_districthomepage_title_suffix.py b/district/migrations/0060_districthomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..a68970fe2b9d9427b6d9e8a521e7403d00f87280
--- /dev/null
+++ b/district/migrations/0060_districthomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 12:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("district", "0059_alter_districtprogrampage_content"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="districthomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/district/models.py b/district/models.py
index 2d51744f97f4bdf724faa4918e0184299f2df390..422007798f349f00e02c789bcc77f4e39d941948 100644
--- a/district/models.py
+++ b/district/models.py
@@ -26,7 +26,13 @@ from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
 from calendar_utils.models import CalendarMixin
-from shared.models import ArticleMixin, MenuMixin, SubpageMixin
+from shared.models import (
+    ArticleMixin,
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    MenuMixin,
+    SubpageMixin,
+)
 from shared.utils import make_promote_panels
 from tuning import admin_help
 from uniweb.constants import RICH_TEXT_FEATURES
@@ -35,7 +41,9 @@ from . import blocks
 from .forms import JekyllImportForm
 
 
-class DistrictHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page):
+class DistrictHomePage(
+    MenuMixin, ExtendedMetadataHomePageMixin, MetadataPageMixin, CalendarMixin, Page
+):
     ### FIELDS
 
     subheader = StreamField(
@@ -188,6 +196,7 @@ class DistrictHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page):
     settings_panels = [
         ImageChooserPanel("custom_logo"),
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         MultiFieldPanel(
             [
                 FieldPanel("show_pirati_cz_link"),
@@ -327,7 +336,9 @@ class DistrictArticleTag(TaggedItemBase):
     )
 
 
-class DistrictArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
+class DistrictArticlePage(
+    ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     author_page = models.ForeignKey(
@@ -370,7 +381,9 @@ class DistrictArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class DistrictArticlesPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictArticlesPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     last_import_log = models.TextField(
@@ -442,7 +455,9 @@ class DistrictArticlesPage(SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class DistrictContactPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictContactPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     contact_people = StreamField(
@@ -474,7 +489,9 @@ class DistrictContactPage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Kontakty"
 
 
-class DistrictTagsPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictTagsPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### PANELS
 
     promote_panels = make_promote_panels()
@@ -568,7 +585,9 @@ class DistrictPersonPageForm(WagtailAdminPageForm):
         return cleaned_data
 
 
-class DistrictPersonPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictPersonPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
     base_form_class = DistrictPersonPageForm
 
@@ -696,7 +715,9 @@ class DistrictPersonPage(SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class DistrictPeoplePage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictPeoplePage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     content = StreamField(
@@ -724,7 +745,9 @@ class DistrictPeoplePage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Lidé"
 
 
-class DistrictElectionBasePage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictElectionBasePage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
     text = RichTextField("text", blank=True, features=RICH_TEXT_FEATURES)
 
@@ -784,7 +807,9 @@ class DistrictElectionPointPage(DistrictElectionBasePage):
         verbose_name = "Bod programu voleb"
 
 
-class DistrictElectionPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictElectionPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
     header = StreamField(
         [("election_header_block", blocks.ElectionHeaderBlock())],
@@ -838,7 +863,9 @@ class DistrictElectionPage(SubpageMixin, MetadataPageMixin, Page):
             return None
 
 
-class DistrictProgramPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictProgramPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     perex = models.TextField("Perex", blank=True)
@@ -879,7 +906,9 @@ class DistrictProgramPage(SubpageMixin, MetadataPageMixin, Page):
         return super().save(**kwargs)
 
 
-class DistrictCenterPage(CalendarMixin, SubpageMixin, MetadataPageMixin, Page):
+class DistrictCenterPage(
+    CalendarMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
     # TODO tohle by šlo asi nahradit DistrictCustomPage
 
@@ -947,7 +976,9 @@ class DistrictCenterPage(CalendarMixin, SubpageMixin, MetadataPageMixin, Page):
         return self.calendar_id is not None
 
 
-class DistrictCrossroadPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictCrossroadPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
 
     ### FIELDS
 
@@ -1000,7 +1031,9 @@ class DistrictCrossroadPage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Rozcestník s kartami"
 
 
-class DistrictCustomPage(SubpageMixin, MetadataPageMixin, Page):
+class DistrictCustomPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
 
     ### FIELDS
 
diff --git a/districts/migrations/0002_districtshomepage_title_suffix.py b/districts/migrations/0002_districtshomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..47d8a1baf7dd94a60f5fcdac40685cfc1fe580b6
--- /dev/null
+++ b/districts/migrations/0002_districtshomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("districts", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="districtshomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/districts/models.py b/districts/models.py
index 1d21e97e6020aa6936e754d456701a38a08c67ae..994811f6357d203788e72db95342f5b093ae2841 100644
--- a/districts/models.py
+++ b/districts/models.py
@@ -10,10 +10,11 @@ from wagtail.core.models import Page
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
+from shared.models import ExtendedMetadataHomePageMixin
 from tuning import admin_help
 
 
-class DistrictsHomePage(MetadataPageMixin, Page):
+class DistrictsHomePage(ExtendedMetadataHomePageMixin, MetadataPageMixin, Page):
     ### FIELDS
 
     matomo_id = models.IntegerField(
@@ -34,7 +35,11 @@ class DistrictsHomePage(MetadataPageMixin, Page):
         ),
     ]
 
-    settings_panels = [FieldPanel("matomo_id"), CommentPanel()]
+    settings_panels = [
+        FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
+        CommentPanel(),
+    ]
 
     ### RELATIONS
 
diff --git a/donate/migrations/0017_donatehomepage_title_suffix.py b/donate/migrations/0017_donatehomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa301ebaa360599c1428ab119ce16cdb9cfe1eff
--- /dev/null
+++ b/donate/migrations/0017_donatehomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("donate", "0016_alter_donateprojectpage_form_title"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="donatehomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/donate/models.py b/donate/models.py
index f340fc05de2dfb9cb128ead2fadce730390e4316..be9a55ab82b1d09b334613f33feaa7743c618f80 100644
--- a/donate/models.py
+++ b/donate/models.py
@@ -20,7 +20,11 @@ from wagtail.images.blocks import ImageChooserBlock
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
-from shared.models import SubpageMixin
+from shared.models import (
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+)
 from shared.utils import get_subpage_url, make_promote_panels
 from tuning import admin_help
 
@@ -74,7 +78,13 @@ class DonateFormAmountsMixin(models.Model):
         abstract = True
 
 
-class DonateHomePage(DonateFormMixin, DonateFormAmountsMixin, Page, MetadataPageMixin):
+class DonateHomePage(
+    DonateFormMixin,
+    DonateFormAmountsMixin,
+    Page,
+    ExtendedMetadataHomePageMixin,
+    MetadataPageMixin,
+):
     ### FIELDS
 
     # lead section
@@ -147,6 +157,7 @@ class DonateHomePage(DonateFormMixin, DonateFormAmountsMixin, Page, MetadataPage
             "sociální sítě",
         ),
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         MultiFieldPanel(
             [
                 FieldPanel("portal_project_id"),
@@ -217,7 +228,9 @@ class DonateHomePage(DonateFormMixin, DonateFormAmountsMixin, Page, MetadataPage
         return context
 
 
-class DonateRegionIndexPage(Page, SubpageMixin, MetadataPageMixin):
+class DonateRegionIndexPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### PANELS
 
     promote_panels = make_promote_panels()
@@ -244,7 +257,12 @@ class DonateRegionIndexPage(Page, SubpageMixin, MetadataPageMixin):
 
 
 class DonateRegionPage(
-    DonateFormMixin, DonateFormAmountsMixin, Page, SubpageMixin, MetadataPageMixin
+    DonateFormMixin,
+    DonateFormAmountsMixin,
+    Page,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+    MetadataPageMixin,
 ):
     ### FIELDS
 
@@ -292,9 +310,6 @@ class DonateRegionPage(
     class Meta:
         verbose_name = "Kraj"
 
-    def get_meta_title(self):
-        return self.seo_title or self.main_title
-
     @cached_property
     def targeted_donations_page_url(self):
         return get_subpage_url(self, DonateTargetedDonationsPage)
@@ -304,7 +319,9 @@ class DonateRegionPage(
         return self.get_descendants().type(DonateTargetedDonationsPage).live().exists()
 
 
-class DonateProjectIndexPage(Page, SubpageMixin, MetadataPageMixin):
+class DonateProjectIndexPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### PANELS
 
     promote_panels = make_promote_panels()
@@ -345,7 +362,12 @@ class DonateProjectIndexPage(Page, SubpageMixin, MetadataPageMixin):
 
 
 class DonateProjectPage(
-    DonateFormMixin, DonateFormAmountsMixin, Page, SubpageMixin, MetadataPageMixin
+    DonateFormMixin,
+    DonateFormAmountsMixin,
+    Page,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+    MetadataPageMixin,
 ):
     TITLE_PROJECT = "project"
     TITLE_CAMPAIGN = "camapign"
@@ -443,9 +465,6 @@ class DonateProjectPage(
     def get_meta_image(self):
         return self.photo
 
-    def get_meta_title(self):
-        return self.seo_title or self.title
-
     def get_meta_description(self):
         if self.search_description:
             return self.search_description
@@ -495,7 +514,7 @@ class DonateProjectPage(
         return super().get_template(request, *args, **kwargs)
 
 
-class DonateTextPage(Page, SubpageMixin, MetadataPageMixin):
+class DonateTextPage(Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin):
     ### FIELDS
 
     body = RichTextField("obsah", blank=True)
@@ -522,7 +541,9 @@ class DonateTextPage(Page, SubpageMixin, MetadataPageMixin):
         verbose_name = "Stránka s textem"
 
 
-class DonateInfoPage(DonateFormMixin, Page, SubpageMixin, MetadataPageMixin):
+class DonateInfoPage(
+    DonateFormMixin, Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     body = RichTextField("obsah", blank=True)
@@ -582,7 +603,7 @@ class TargetedDonation(Orderable):
 
 
 class DonateTargetedDonationsPage(
-    DonateFormMixin, Page, SubpageMixin, MetadataPageMixin
+    DonateFormMixin, Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
 ):
     ### FIELDS
 
diff --git a/green_deal/migrations/0006_greendealhomepage_title_suffix.py b/green_deal/migrations/0006_greendealhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..fcf23a63eeddbba28ff4fd37a32ce12c5454ee46
--- /dev/null
+++ b/green_deal/migrations/0006_greendealhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("green_deal", "0005_auto_20210118_0721"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="greendealhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/green_deal/models.py b/green_deal/models.py
index d4e05d8fdaa5f354c3ec8cdfa9d2157ed6c7109b..7af63847809f8aa05432d3147620811327c3b564 100644
--- a/green_deal/models.py
+++ b/green_deal/models.py
@@ -15,6 +15,7 @@ from wagtail.images.blocks import ImageChooserBlock
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
+from shared.models import ExtendedMetadataHomePageMixin, ExtendedMetadataPageMixin
 from tuning import admin_help
 
 RICH_TEXT_FEATURES = [
@@ -82,7 +83,7 @@ class StudiesBlock(blocks.StructBlock):
         icon = "doc-full"
 
 
-class GreenDealHomePage(MetadataPageMixin, Page):
+class GreenDealHomePage(ExtendedMetadataHomePageMixin, MetadataPageMixin, Page):
     ### FIELDS
     content = StreamField(
         [
@@ -124,6 +125,7 @@ class GreenDealHomePage(MetadataPageMixin, Page):
 
     settings_panels = [
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         StreamFieldPanel("top_menu"),
         CommentPanel(),
     ]
@@ -144,7 +146,7 @@ class GreenDealHomePage(MetadataPageMixin, Page):
         return self
 
 
-class GreenDealSubPage(Page, MetadataPageMixin):
+class GreenDealSubPage(Page, ExtendedMetadataPageMixin, MetadataPageMixin):
     ### FIELDS
     content = StreamField(
         [
diff --git a/region/migrations/0035_regionhomepage_title_suffix.py b/region/migrations/0035_regionhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..7059c69ff24bf52574355b18b457f608cbc881de
--- /dev/null
+++ b/region/migrations/0035_regionhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("region", "0034_alter_regionprogrampage_content"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="regionhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/region/models.py b/region/models.py
index 434ed8deb13b605a45c15ce9adc5d07dfdc527bb..109dfc959908849e81c7c628c375d782eee84e0a 100644
--- a/region/models.py
+++ b/region/models.py
@@ -26,7 +26,13 @@ from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
 from calendar_utils.models import CalendarMixin
-from shared.models import ArticleMixin, MenuMixin, SubpageMixin
+from shared.models import (
+    ArticleMixin,
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    MenuMixin,
+    SubpageMixin,
+)
 from shared.utils import make_promote_panels
 from tuning import admin_help
 from uniweb.constants import RICH_TEXT_FEATURES
@@ -35,7 +41,9 @@ from . import blocks
 from .forms import JekyllImportForm
 
 
-class RegionHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page):
+class RegionHomePage(
+    MenuMixin, ExtendedMetadataHomePageMixin, MetadataPageMixin, CalendarMixin, Page
+):
     ### FIELDS
 
     subheader = StreamField(
@@ -188,6 +196,7 @@ class RegionHomePage(MenuMixin, MetadataPageMixin, CalendarMixin, Page):
     settings_panels = [
         ImageChooserPanel("custom_logo"),
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         MultiFieldPanel(
             [
                 FieldPanel("show_pirati_cz_link"),
@@ -317,7 +326,9 @@ class RegionArticleTag(TaggedItemBase):
     content_object = ParentalKey("region.RegionArticlePage", on_delete=models.CASCADE)
 
 
-class RegionArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
+class RegionArticlePage(
+    ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     author_page = models.ForeignKey(
@@ -360,7 +371,9 @@ class RegionArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class RegionArticlesPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionArticlesPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     last_import_log = models.TextField(
@@ -429,7 +442,9 @@ class RegionArticlesPage(SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class RegionContactPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionContactPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     contact_people = StreamField(
@@ -461,7 +476,7 @@ class RegionContactPage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Kontakty"
 
 
-class RegionTagsPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionTagsPage(ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page):
     ### PANELS
 
     promote_panels = make_promote_panels()
@@ -553,7 +568,9 @@ class RegionPersonPageForm(WagtailAdminPageForm):
         return cleaned_data
 
 
-class RegionPersonPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionPersonPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     base_form_class = RegionPersonPageForm
     ### FIELDS
 
@@ -680,7 +697,9 @@ class RegionPersonPage(SubpageMixin, MetadataPageMixin, Page):
         return context
 
 
-class RegionPeoplePage(SubpageMixin, MetadataPageMixin, Page):
+class RegionPeoplePage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     content = StreamField(
@@ -708,7 +727,9 @@ class RegionPeoplePage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Lidé"
 
 
-class RegionElectionBasePage(SubpageMixin, MetadataPageMixin, Page):
+class RegionElectionBasePage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     text = RichTextField("text", blank=True, features=RICH_TEXT_FEATURES)
@@ -767,7 +788,9 @@ class RegionElectionPointPage(RegionElectionBasePage):
         verbose_name = "Bod programu voleb"
 
 
-class RegionElectionPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionElectionPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
     header = StreamField(
         [("election_header_block", blocks.ElectionHeaderBlock())],
@@ -825,7 +848,9 @@ class RegionElectionPage(SubpageMixin, MetadataPageMixin, Page):
             return None
 
 
-class RegionProgramPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionProgramPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     perex = models.TextField("Perex", blank=True)
@@ -866,7 +891,9 @@ class RegionProgramPage(SubpageMixin, MetadataPageMixin, Page):
         return super().save(**kwargs)
 
 
-class RegionCenterPage(CalendarMixin, SubpageMixin, MetadataPageMixin, Page):
+class RegionCenterPage(
+    CalendarMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     perex = models.TextField("Perex", blank=True, null=True)
@@ -933,7 +960,9 @@ class RegionCenterPage(CalendarMixin, SubpageMixin, MetadataPageMixin, Page):
         return self.calendar_id is not None
 
 
-class RegionCrossroadPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionCrossroadPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
 
     ### FIELDS
 
@@ -986,7 +1015,9 @@ class RegionCrossroadPage(SubpageMixin, MetadataPageMixin, Page):
         verbose_name = "Rozcestník s kartami"
 
 
-class RegionCustomPage(SubpageMixin, MetadataPageMixin, Page):
+class RegionCustomPage(
+    ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
 
     ### FIELDS
 
diff --git a/regulace_konopi/migrations/0009_regkonhomepage_title_suffix.py b/regulace_konopi/migrations/0009_regkonhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..de89353c3d9ac5fa1c34b5aee90de90de17aa23c
--- /dev/null
+++ b/regulace_konopi/migrations/0009_regkonhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("regulace_konopi", "0008_auto_20210118_1259"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="regkonhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/regulace_konopi/models.py b/regulace_konopi/models.py
index 988f9bdb14e967c29d61de55cf52d0759dfe5388..50174db490ae15ebd38e88e014c0a50e72462c53 100644
--- a/regulace_konopi/models.py
+++ b/regulace_konopi/models.py
@@ -14,6 +14,7 @@ from wagtail.images.blocks import ImageChooserBlock
 from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
+from shared.models import ExtendedMetadataHomePageMixin, ExtendedMetadataPageMixin
 from tuning import admin_help
 
 SUPPORT_CHOICES = ((1, "Pro"), (0, "Proti"), (-1, "Nevíme"))
@@ -75,7 +76,7 @@ class ThreeColumnsBlock(blocks.StructBlock):
     second_column = blocks.RichTextBlock(features=RICH_TEXT_FEATURES)
 
 
-class RegkonHomePage(MetadataPageMixin, Page):
+class RegkonHomePage(ExtendedMetadataHomePageMixin, MetadataPageMixin, Page):
     ### FIELDS
     content = StreamField(
         [
@@ -137,6 +138,7 @@ class RegkonHomePage(MetadataPageMixin, Page):
 
     settings_panels = [
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         StreamFieldPanel("top_menu"),
         CommentPanel(),
     ]
@@ -157,7 +159,7 @@ class RegkonHomePage(MetadataPageMixin, Page):
         return self
 
 
-class RegkonSubPage(Page, MetadataPageMixin):
+class RegkonSubPage(Page, ExtendedMetadataPageMixin, MetadataPageMixin):
     ### FIELDS
 
     content = StreamField(
diff --git a/senat_campaign/migrations/0008_senatcampaignhomepage_title_suffix.py b/senat_campaign/migrations/0008_senatcampaignhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..2b9d7041e0de97896a9c58be7470f428d237d8e4
--- /dev/null
+++ b/senat_campaign/migrations/0008_senatcampaignhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("senat_campaign", "0007_auto_20200603_1815"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="senatcampaignhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/senat_campaign/models.py b/senat_campaign/models.py
index 71812244007f65729f0cf72f936e8285f6b70255..d393be6b80f9f74f427779bee5a3ffd721ca6c03 100644
--- a/senat_campaign/models.py
+++ b/senat_campaign/models.py
@@ -18,7 +18,11 @@ from wagtail.images.edit_handlers import ImageChooserPanel
 from wagtailmetadata.models import MetadataPageMixin
 
 from calendar_utils.models import CalendarMixin
-from shared.models import SubpageMixin
+from shared.models import (
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+)
 from tuning import admin_help
 
 HELP_COMBINED_TITLE = (
@@ -27,13 +31,6 @@ HELP_COMBINED_TITLE = (
 )
 
 
-class MetaMixin:
-    def get_meta_title(self):
-        if self.seo_title:
-            return self.seo_title
-        return f"{self.title} | {self.root_page.full_name}"
-
-
 class ContactBlock(blocks.StructBlock):
     name = blocks.CharBlock(label="jméno")
     job = blocks.CharBlock(label="pozice", required=False)
@@ -46,7 +43,9 @@ class ContactBlock(blocks.StructBlock):
         label = "kontaktní osoba"
 
 
-class SenatCampaignHomePage(Page, MetadataPageMixin, CalendarMixin):
+class SenatCampaignHomePage(
+    Page, ExtendedMetadataHomePageMixin, MetadataPageMixin, CalendarMixin
+):
     ### FIELDS
 
     # top section
@@ -182,6 +181,7 @@ class SenatCampaignHomePage(Page, MetadataPageMixin, CalendarMixin):
         ),
         FieldPanel("calendar_url"),
         FieldPanel("matomo_id"),
+        FieldPanel("title_suffix"),
         StreamFieldPanel("contacts"),
         CommentPanel(),
     ]
@@ -280,7 +280,9 @@ class SenatCampaignHomePage(Page, MetadataPageMixin, CalendarMixin):
         return context
 
 
-class SenatCampaignNewsIndexPage(Page, SubpageMixin, MetaMixin, MetadataPageMixin):
+class SenatCampaignNewsIndexPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     ### PANELS
@@ -334,7 +336,9 @@ class SenatCampaignNewsIndexPage(Page, SubpageMixin, MetaMixin, MetadataPageMixi
         return context
 
 
-class SenatCampaignNewsPage(Page, SubpageMixin, MetaMixin, MetadataPageMixin):
+class SenatCampaignNewsPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     date = models.DateField("datum")
@@ -430,7 +434,9 @@ class ProgramBlock(blocks.StructBlock):
         label = "programový bod"
 
 
-class SenatCampaignProgramPage(Page, SubpageMixin, MetaMixin, MetadataPageMixin):
+class SenatCampaignProgramPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     committee_preference = StreamField(
@@ -480,7 +486,9 @@ class SenatCampaignProgramPage(Page, SubpageMixin, MetaMixin, MetadataPageMixin)
         verbose_name = "Program"
 
 
-class SenatCampaignCookiesPage(Page, SubpageMixin, MetaMixin, MetadataPageMixin):
+class SenatCampaignCookiesPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     body = RichTextField("obsah", blank=True)
diff --git a/shared/models.py b/shared/models.py
index adc305d01087f588e80c0910827d406f16b7744b..827df2668691cb4deee95a4ef62894ea5f1343df 100644
--- a/shared/models.py
+++ b/shared/models.py
@@ -1,3 +1,5 @@
+import logging
+
 from django.db import models
 from django.utils import timezone
 from wagtail.admin.edit_handlers import (
@@ -18,6 +20,8 @@ from shared.blocks import (
     YouTubeVideoBlock,
 )
 
+logger = logging.getLogger(__name__)
+
 
 class SubpageMixin:
     """Must be used in class definition before MetadataPageMixin!"""
@@ -138,3 +142,84 @@ class MenuMixin(Page):
 
     class Meta:
         abstract = True
+
+
+class ExtendedMetadataHomePageMixin(models.Model):
+    """Use for site home page to define metadata title suffix.
+
+    Must be used in class definition before MetadataPageMixin!
+    """
+
+    title_suffix = models.CharField(
+        "Přípona titulku stránky",
+        max_length=100,
+        blank=True,
+        null=True,
+        help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud "
+        "je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte "
+        "'MS Pardubice | Piráti', výsledný titulek bude "
+        "'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije "
+        "se název webu.",
+    )
+
+    class Meta:
+        abstract = True
+
+    def get_meta_title_suffix(self):
+        if self.title_suffix:
+            return self.title_suffix
+
+        if hasattr(super(), "get_meta_title"):
+            return super().get_meta_title()
+
+        return self.get_site().site_name
+
+    def get_meta_title(self):
+        title = super().get_meta_title()
+        suffix = self.get_meta_title_suffix()
+
+        # Covers scenario when title_suffix is not set and evaluates to super().get_meta_title() value.
+        # Rather than having MS Pardubice | MS Pardubice, just use MS Pardubice alone.
+        if title != suffix:
+            return f"{super().get_meta_title()} | {self.get_meta_title_suffix()}"
+
+        return title
+
+
+class ExtendedMetadataPageMixin(models.Model):
+    """Use for pages except for home page to use shared metadata title suffix.
+
+    There are few rules on how to use this:
+
+    - Do not forget to list ExtendedMetadataHomePageMixin among ancestors of the related HomePage class.
+    - Must be used in class definition before MetadataPageMixin.
+    - Expects SubpageMixin or equivalent exposing `root_page` property to be used for the page too.
+    """
+
+    class Meta:
+        abstract = True
+
+    def get_meta_title_suffix(self):
+        if not hasattr(self, "root_page"):
+            logger.warning(
+                "Using `ExtendedMetadataPageMixin` without `SubpageMixin` for %s",
+                repr(self),
+            )
+            return None
+
+        if not hasattr(self.root_page, "get_meta_title_suffix"):
+            logger.warning(
+                "Using `ExtendedMetadataPageMixin` without `ExtendedMetadataHomePageMixin` on the root page for %s",
+                repr(self),
+            )
+            return None
+
+        return self.root_page.get_meta_title_suffix()
+
+    def get_meta_title(self):
+        suffix = self.get_meta_title_suffix()
+
+        if not suffix:
+            return super().get_meta_title()
+
+        return f"{super().get_meta_title()} | {self.get_meta_title_suffix()}"
diff --git a/uniweb/migrations/0025_uniwebhomepage_title_suffix.py b/uniweb/migrations/0025_uniwebhomepage_title_suffix.py
new file mode 100644
index 0000000000000000000000000000000000000000..c0ba7a168c4e373195ecc19490433e8c87b4b822
--- /dev/null
+++ b/uniweb/migrations/0025_uniwebhomepage_title_suffix.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-04-27 13:27
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("uniweb", "0024_alter_uniwebarticlepage_content"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="uniwebhomepage",
+            name="title_suffix",
+            field=models.CharField(
+                blank=True,
+                help_text="Umožňuje přidat příponu k základnímu titulku stránky. Pokud je např. titulek stránky pojmenovaný 'Kontakt' a do přípony vyplníte 'MS Pardubice | Piráti', výsledný titulek bude 'Kontakt | MS Pardubice | Piráti'. Pokud příponu nevyplníte, použije se název webu.",
+                max_length=100,
+                null=True,
+                verbose_name="Přípona titulku stránky",
+            ),
+        ),
+    ]
diff --git a/uniweb/models.py b/uniweb/models.py
index d279eb022d60c1a27edc0193f201b2c199677544..ec9d9543aa7a73e70e26782ee7103ae6fff80623 100644
--- a/uniweb/models.py
+++ b/uniweb/models.py
@@ -26,7 +26,12 @@ from wagtail.images.blocks import ImageChooserBlock
 from wagtailmetadata.models import MetadataPageMixin
 
 from calendar_utils.models import CalendarMixin
-from shared.models import ArticleMixin, SubpageMixin
+from shared.models import (
+    ArticleMixin,
+    ExtendedMetadataHomePageMixin,
+    ExtendedMetadataPageMixin,
+    SubpageMixin,
+)
 from shared.utils import make_promote_panels
 from tuning import admin_help
 
@@ -285,7 +290,9 @@ class UniwebArticleTag(TaggedItemBase):
     content_object = ParentalKey("uniweb.UniwebArticlePage", on_delete=models.CASCADE)
 
 
-class UniwebHomePage(Page, MetadataPageMixin, CalendarMixin):
+class UniwebHomePage(
+    Page, ExtendedMetadataHomePageMixin, MetadataPageMixin, CalendarMixin
+):
     ### FIELDS
 
     content = StreamField(
@@ -330,6 +337,7 @@ class UniwebHomePage(Page, MetadataPageMixin, CalendarMixin):
         MultiFieldPanel(
             [
                 FieldPanel("matomo_id"),
+                FieldPanel("title_suffix"),
                 FieldPanel("narrow_layout"),
             ],
             "nastavení webu",
@@ -380,7 +388,9 @@ class UniwebHomePage(Page, MetadataPageMixin, CalendarMixin):
         return self.calendar_id is not None
 
 
-class UniwebFlexiblePage(Page, SubpageMixin, MetadataPageMixin):
+class UniwebFlexiblePage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     content = StreamField(
@@ -412,7 +422,9 @@ class UniwebFlexiblePage(Page, SubpageMixin, MetadataPageMixin):
         verbose_name = "Flexibilní stránka"
 
 
-class UniwebArticlesIndexPage(Page, SubpageMixin, MetadataPageMixin):
+class UniwebArticlesIndexPage(
+    Page, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     ### PANELS
@@ -450,7 +462,9 @@ class UniwebArticlesIndexPage(Page, SubpageMixin, MetadataPageMixin):
         return context
 
 
-class UniwebArticlePage(ArticleMixin, SubpageMixin, MetadataPageMixin, Page):
+class UniwebArticlePage(
+    ArticleMixin, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin, Page
+):
     ### FIELDS
 
     tags = ClusterTaggableManager(through=UniwebArticleTag, blank=True)
@@ -491,7 +505,9 @@ class UniwebFormField(AbstractFormField):
     )
 
 
-class UniwebFormPage(AbstractForm, SubpageMixin, MetadataPageMixin):
+class UniwebFormPage(
+    AbstractForm, ExtendedMetadataPageMixin, SubpageMixin, MetadataPageMixin
+):
     ### FIELDS
 
     content_before = StreamField(