From e71ebe60d18c1bf7eec85f87be61fcd276c54b97 Mon Sep 17 00:00:00 2001 From: Dawid Pers Date: Wed, 4 Feb 2026 15:01:22 +0100 Subject: [PATCH 1/5] fix SEO category title with slug fallback --- package.json | 2 +- src/helpers/UtilsHelper.ts | 10 ++++++++-- src/helpers/seo/SeoTitleHelper.ts | 9 +++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index eb163be7..2b6bef56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hat-ring-components", - "version": "4.6.2", + "version": "4.6.3", "description": "Head App Template - RING components", "license": "MIT", "repository": {}, diff --git a/src/helpers/UtilsHelper.ts b/src/helpers/UtilsHelper.ts index 123580bb..c0538d83 100644 --- a/src/helpers/UtilsHelper.ts +++ b/src/helpers/UtilsHelper.ts @@ -51,6 +51,12 @@ export function UtilsHelper_getCurrentPageType(context) { return isHomePage ? SiteContentType.Homepage : (context.siteContentType || null); } +export function UtilsHelper_formatSlugToTitle(slug: string): string { + if (!slug) return ''; + const formattedSlug = slug.replaceAll('-', ' '); + return formattedSlug.charAt(0).toUpperCase() + formattedSlug.slice(1); +} + export function UtilsHelper_getCurrentNodeName(context) { try { const content = context?.hatControllerParams?.gqlResponse?.data?.site?.data?.content; @@ -59,8 +65,8 @@ export function UtilsHelper_getCurrentNodeName(context) { if (pageType === SiteContentType.SiteNode) { // @TODO: getting name for sitenode/category in HAT Server? - const slug = content.slug?.replaceAll('-', ' ') || ''; - return (slug.charAt(0).toUpperCase() + slug.slice(1)) || ''; + const slug = content.slug || ''; + return UtilsHelper_formatSlugToTitle(slug); } else if (pageType === SiteContentType.Story) { return content.title || ''; } else if (pageType === SiteContentType.CustomAction) { diff --git a/src/helpers/seo/SeoTitleHelper.ts b/src/helpers/seo/SeoTitleHelper.ts index ebf3bc46..998723d1 100644 --- a/src/helpers/seo/SeoTitleHelper.ts +++ b/src/helpers/seo/SeoTitleHelper.ts @@ -8,7 +8,7 @@ import {WebsiteApiProvider} from "../../providers/WebsiteApiProvider"; import {gql} from "graphql-tag"; import _ from "lodash"; import {SeoHelper_getSeoCurrentPageType} from "./SeoHelper"; -import {UtilsHelper_getDomain} from "../UtilsHelper"; +import {UtilsHelper_getDomain, UtilsHelper_formatSlugToTitle} from "../UtilsHelper"; /** * Helper for handling titles according to the SEO requirements based on the placement of the usage @@ -95,6 +95,7 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { site(url:$url, variantId: $variant){ data { node { + slug category { data{ name @@ -111,7 +112,11 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { variant: context.websiteManagerVariant, }); - return _.get(nodeResponse, 'data.site.data.node.category.data.name', ''); + const categoryName = _.get(nodeResponse, 'data.site.data.node.category.data.name', ''); + if (categoryName) return categoryName; + + const slug = _.get(nodeResponse, 'data.site.data.node.slug', ''); + return UtilsHelper_formatSlugToTitle(slug); } async function prepareCategoryTitle() { From f6cf42c831720e9fbf5ebfde405ae2d5e7340364 Mon Sep 17 00:00:00 2001 From: Dawid Pers Date: Thu, 5 Feb 2026 14:32:27 +0100 Subject: [PATCH 2/5] add get category name from context --- src/helpers/seo/SeoTitleHelper.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/helpers/seo/SeoTitleHelper.ts b/src/helpers/seo/SeoTitleHelper.ts index 998723d1..7c30bea1 100644 --- a/src/helpers/seo/SeoTitleHelper.ts +++ b/src/helpers/seo/SeoTitleHelper.ts @@ -27,7 +27,7 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { return await prepareStoryTitle(); case 'SiteNode': - return await prepareCategoryTitle(); + return await prepareCategoryTitle(context); case 'Homepage': default: @@ -89,7 +89,10 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { } } - async function getCategoryName() { + async function getCategoryName(context) { + const categoryNameFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.category.data.name', ""); + if (categoryNameFromContext) return categoryNameFromContext; + const nodeQuery = gql` query($url: URL!, $variant:ID!){ site(url:$url, variantId: $variant){ @@ -114,13 +117,16 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { const categoryName = _.get(nodeResponse, 'data.site.data.node.category.data.name', ''); if (categoryName) return categoryName; - + + const slugFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.slug') || _.get(context, 'hatControllerParams.gqlResponse.data.site.data.content.slug'); + if (slugFromContext) return UtilsHelper_formatSlugToTitle(slugFromContext); + const slug = _.get(nodeResponse, 'data.site.data.node.slug', ''); return UtilsHelper_formatSlugToTitle(slug); } - async function prepareCategoryTitle() { - const categoryName = await getCategoryName(); + async function prepareCategoryTitle(context) { + const categoryName = await getCategoryName(context); switch (place) { case 'default': From 82938be76ee82843aa67627aa058124ffccdd79f Mon Sep 17 00:00:00 2001 From: Dawid Pers Date: Thu, 5 Feb 2026 16:20:37 +0100 Subject: [PATCH 3/5] add optimization for queries in seo helpers --- src/helpers/UtilsHelper.ts | 9 ++++----- src/helpers/seo/SeoHelper.ts | 3 +++ src/helpers/seo/SeoTitleHelper.ts | 24 ++++++++++++++++-------- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/helpers/UtilsHelper.ts b/src/helpers/UtilsHelper.ts index c0538d83..8c4d9efc 100644 --- a/src/helpers/UtilsHelper.ts +++ b/src/helpers/UtilsHelper.ts @@ -61,10 +61,10 @@ export function UtilsHelper_getCurrentNodeName(context) { try { const content = context?.hatControllerParams?.gqlResponse?.data?.site?.data?.content; if (content) { - const pageType = UtilsHelper_getCurrentPageType(context); - + const pageType = UtilsHelper_getCurrentPageType(context); if (pageType === SiteContentType.SiteNode) { - // @TODO: getting name for sitenode/category in HAT Server? + const categoryName = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.category.data.name', ''); + if (categoryName) return categoryName; const slug = content.slug || ''; return UtilsHelper_formatSlugToTitle(slug); } else if (pageType === SiteContentType.Story) { @@ -74,8 +74,7 @@ export function UtilsHelper_getCurrentNodeName(context) { } else if ([SiteContentType.Source, SiteContentType.Topic].includes(pageType)) { return content.name || ''; } else if (pageType === SiteContentType.Author) { - // @TODO: get author name in HAT Server - return ''; + return content.name || ''; } } } catch (e) { diff --git a/src/helpers/seo/SeoHelper.ts b/src/helpers/seo/SeoHelper.ts index 89b73a74..56581ddd 100644 --- a/src/helpers/seo/SeoHelper.ts +++ b/src/helpers/seo/SeoHelper.ts @@ -152,6 +152,9 @@ export async function SeoHelper_getSeoCurrentPageType(context) { export async function SeoHelper_authorName(context) { + const authorNameFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.content.name', ''); + if (authorNameFromContext) return authorNameFromContext; + const query = gql` query($uuid: UUID){ author(id:$uuid){ diff --git a/src/helpers/seo/SeoTitleHelper.ts b/src/helpers/seo/SeoTitleHelper.ts index 7c30bea1..e6228386 100644 --- a/src/helpers/seo/SeoTitleHelper.ts +++ b/src/helpers/seo/SeoTitleHelper.ts @@ -27,7 +27,7 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { return await prepareStoryTitle(); case 'SiteNode': - return await prepareCategoryTitle(context); + return await prepareCategoryTitle(); case 'Homepage': default: @@ -35,6 +35,17 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { } async function getStoryTitles() { + const dataContent = context?.hatControllerParams?.gqlResponse?.data?.site?.data?.content; + const titleFromContext = _.get(dataContent, 'title', ''); + const leadsFromContext = _.get(dataContent, 'leads', []); + + if (titleFromContext && leadsFromContext.length) { + return { + title: titleFromContext, + leads: leadsFromContext + }; + } + const storyQuery = gql` query($storyId: UUID){ story(id:$storyId){ @@ -89,8 +100,8 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { } } - async function getCategoryName(context) { - const categoryNameFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.category.data.name', ""); + async function getCategoryName() { + const categoryNameFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.category.data.name', ''); if (categoryNameFromContext) return categoryNameFromContext; const nodeQuery = gql` @@ -118,15 +129,12 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { const categoryName = _.get(nodeResponse, 'data.site.data.node.category.data.name', ''); if (categoryName) return categoryName; - const slugFromContext = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.slug') || _.get(context, 'hatControllerParams.gqlResponse.data.site.data.content.slug'); - if (slugFromContext) return UtilsHelper_formatSlugToTitle(slugFromContext); - const slug = _.get(nodeResponse, 'data.site.data.node.slug', ''); return UtilsHelper_formatSlugToTitle(slug); } - async function prepareCategoryTitle(context) { - const categoryName = await getCategoryName(context); + async function prepareCategoryTitle() { + const categoryName = await getCategoryName(); switch (place) { case 'default': From dd2e3b6d7be666faa992307535461c78d3902958 Mon Sep 17 00:00:00 2001 From: Dawid Pers Date: Fri, 6 Feb 2026 09:44:05 +0100 Subject: [PATCH 4/5] fix --- src/helpers/UtilsHelper.ts | 7 +------ src/helpers/seo/SeoTitleHelper.ts | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/helpers/UtilsHelper.ts b/src/helpers/UtilsHelper.ts index 8c4d9efc..f43db9e7 100644 --- a/src/helpers/UtilsHelper.ts +++ b/src/helpers/UtilsHelper.ts @@ -51,11 +51,6 @@ export function UtilsHelper_getCurrentPageType(context) { return isHomePage ? SiteContentType.Homepage : (context.siteContentType || null); } -export function UtilsHelper_formatSlugToTitle(slug: string): string { - if (!slug) return ''; - const formattedSlug = slug.replaceAll('-', ' '); - return formattedSlug.charAt(0).toUpperCase() + formattedSlug.slice(1); -} export function UtilsHelper_getCurrentNodeName(context) { try { @@ -66,7 +61,7 @@ export function UtilsHelper_getCurrentNodeName(context) { const categoryName = _.get(context, 'hatControllerParams.gqlResponse.data.site.data.node.category.data.name', ''); if (categoryName) return categoryName; const slug = content.slug || ''; - return UtilsHelper_formatSlugToTitle(slug); + return _.capitalize(UtilsHelper_slugify(slug)); } else if (pageType === SiteContentType.Story) { return content.title || ''; } else if (pageType === SiteContentType.CustomAction) { diff --git a/src/helpers/seo/SeoTitleHelper.ts b/src/helpers/seo/SeoTitleHelper.ts index e6228386..ebfbbe53 100644 --- a/src/helpers/seo/SeoTitleHelper.ts +++ b/src/helpers/seo/SeoTitleHelper.ts @@ -8,7 +8,7 @@ import {WebsiteApiProvider} from "../../providers/WebsiteApiProvider"; import {gql} from "graphql-tag"; import _ from "lodash"; import {SeoHelper_getSeoCurrentPageType} from "./SeoHelper"; -import {UtilsHelper_getDomain, UtilsHelper_formatSlugToTitle} from "../UtilsHelper"; +import {UtilsHelper_getDomain, UtilsHelper_slugify} from "../UtilsHelper"; /** * Helper for handling titles according to the SEO requirements based on the placement of the usage @@ -130,7 +130,7 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { if (categoryName) return categoryName; const slug = _.get(nodeResponse, 'data.site.data.node.slug', ''); - return UtilsHelper_formatSlugToTitle(slug); + return _.capitalize(UtilsHelper_slugify(slug)); } async function prepareCategoryTitle() { From 444d7374eb1daded4b17cbb8dc912ca3f7879599 Mon Sep 17 00:00:00 2001 From: Dawid Pers Date: Fri, 6 Feb 2026 12:07:23 +0100 Subject: [PATCH 5/5] fix --- src/helpers/seo/SeoTitleHelper.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/helpers/seo/SeoTitleHelper.ts b/src/helpers/seo/SeoTitleHelper.ts index ebfbbe53..f50f1113 100644 --- a/src/helpers/seo/SeoTitleHelper.ts +++ b/src/helpers/seo/SeoTitleHelper.ts @@ -35,17 +35,6 @@ export async function SeoTitleHelper_pageTitle(context, place: string) { } async function getStoryTitles() { - const dataContent = context?.hatControllerParams?.gqlResponse?.data?.site?.data?.content; - const titleFromContext = _.get(dataContent, 'title', ''); - const leadsFromContext = _.get(dataContent, 'leads', []); - - if (titleFromContext && leadsFromContext.length) { - return { - title: titleFromContext, - leads: leadsFromContext - }; - } - const storyQuery = gql` query($storyId: UUID){ story(id:$storyId){